# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: /var/www/html/zabbix/branches/dev/ZBXNEXT-4447/frontends
# This patch can be applied using context Tools: Patch action on respective folder.
# It uses platform neutral UTF-8 encoding and \n newlines.
# Above lines and this line are ignored by the patching process.
Index: php/app/controllers/CControllerWidgetProblemHostsView.php
--- php/app/controllers/CControllerWidgetProblemHostsView.php Base (BASE)
+++ php/app/controllers/CControllerWidgetProblemHostsView.php Locally Modified (Based On LOCAL)
@@ -53,7 +53,7 @@
 			$exclude_groupids = getSubGroups($fields['exclude_groupids']);
 
 			if ($filter_hostids === null) {
-				// get all groups if no selected groups defined
+				// Get all groups if no selected groups defined.
 				if ($filter_groupids === null) {
 					$filter_groupids = array_keys(API::HostGroup()->get([
 						'output' => [],
@@ -63,7 +63,7 @@
 
 				$filter_groupids = array_diff($filter_groupids, $exclude_groupids);
 
-				// get available hosts
+				// Get available hosts.
 				$filter_hostids = array_keys(API::Host()->get([
 					'output' => [],
 					'groupids' => $filter_groupids,
@@ -80,6 +80,7 @@
 			$filter_hostids = array_diff($filter_hostids, $exclude_hostids);
 		}
 
+		// Get host groups.
 		$groups = API::HostGroup()->get([
 			'output' => ['groupid', 'name'],
 			'groupids' => $filter_groupids,
@@ -88,199 +89,137 @@
 			'preservekeys' => true
 		]);
 
-		// get hosts
+		// Get hosts.
 		$hosts = API::Host()->get([
 			'output' => ['hostid', 'name'],
 			'selectGroups' => ['groupid'],
 			'groupids' => array_keys($groups),
 			'hostids' => $filter_hostids,
-			'filter' => ['maintenance_status' => ($filter_maintenance == 0) ? 0 : null],
+			'filter' => [
+				'maintenance_status' => ($filter_maintenance == 0) ? 0 : null
+			],
 			'monitored_hosts' => true,
 			'preservekeys' => true
 		]);
 
-		CArrayHelper::sort($hosts, ['name']);
-		CArrayHelper::sort($groups, ['name']);
-
-		// get triggers
+		// Get triggers.
 		$triggers = API::Trigger()->get([
-			'output' => ['triggerid', 'priority'],
+			'output' => [],
 			'selectHosts' => ['hostid'],
-			'search' => ['description' => $filter_problem],
+			'hostids' => array_keys($hosts),
+			'groupids' => array_keys($groups),
 			'filter' => [
-				'priority' => $filter_severities,
 				'value' => TRIGGER_VALUE_TRUE
 			],
 			'maintenance' => ($filter_maintenance == 0) ? false : null,
-			'monitored' => true
-		]);
-
-		if ($filter_ext_ack != EXTACK_OPTION_ALL) {
-			$hosts_with_unack_triggers = [];
-
-			$triggers_unack = API::Trigger()->get([
-				'output' => ['triggerid'],
-				'selectHosts' => ['hostid'],
-				'search' => ['description' => $filter_problem],
-				'filter' => [
-					'priority' => $filter_severities,
-					'value' => TRIGGER_VALUE_TRUE
-				],
-				'withLastEventUnacknowledged' => true,
-				'maintenance' => ($filter_maintenance == 0) ? false : null,
 				'monitored' => true,
 				'preservekeys' => true
 			]);
 
-			foreach ($triggers_unack as $tunack) {
-				foreach ($tunack['hosts'] as $unack_host) {
-					$hosts_with_unack_triggers[$unack_host['hostid']] = $unack_host['hostid'];
+		// Add default values for each host group and count hosts inside.
+		foreach ($hosts as $host) {
+			foreach ($host['groups'] as $group) {
+				if (!array_key_exists($group['groupid'], $groups)) {
+					continue;
 				}
-			}
-		}
 
-		$hosts_data = [];
-		$problematic_host_list = [];
-		$lastUnack_host_list = [];
-		$highest_severity = [];
-		$highest_severity2 = [];
+				if (!array_key_exists('hosts_total_count', $groups[$group['groupid']])) {
+					$groups[$group['groupid']]['highest_severity'] = 0;
+					$groups[$group['groupid']]['hosts_total_count'] = 0;
+					$groups[$group['groupid']]['hosts_problematic_unack_count'] = 0;
+					$groups[$group['groupid']]['hosts_problematic_unack_list'] = [];
 
-		foreach ($triggers as $trigger) {
-			foreach ($trigger['hosts'] as $trigger_host) {
-				if (!array_key_exists($trigger_host['hostid'], $hosts)) {
-					continue;
+					if ($filter_ext_ack != EXTACK_OPTION_UNACK) {
+						$groups[$group['groupid']]['hosts_problematic_count'] = 0;
+						$groups[$group['groupid']]['hosts_problematic_list'] = [];
 				}
-				else {
-					$host = $hosts[$trigger_host['hostid']];
 				}
 
-				if ($filter_ext_ack != EXTACK_OPTION_ALL
-						&& array_key_exists($host['hostid'], $hosts_with_unack_triggers)) {
-					if (!array_key_exists($host['hostid'], $lastUnack_host_list)) {
-						$lastUnack_host_list[$host['hostid']] = [];
-						$lastUnack_host_list[$host['hostid']]['host'] = $host['name'];
-						$lastUnack_host_list[$host['hostid']]['hostid'] = $host['hostid'];
-
-						$lastUnack_host_list[$host['hostid']]['severities'] = [];
-
-						foreach ($filter_severities as $severity) {
-							$lastUnack_host_list[$host['hostid']]['severities'][$severity] = 0;
+				$groups[$group['groupid']]['hosts_total_count']++;
 						}
 					}
-					if (array_key_exists($trigger['triggerid'], $triggers_unack)) {
-						$lastUnack_host_list[$host['hostid']]['severities'][$trigger['priority']]++;
-					}
 
-					foreach ($host['groups'] as $gnum => $group) {
-						if (!array_key_exists($group['groupid'], $highest_severity2)) {
-							$highest_severity2[$group['groupid']] = 0;
-						}
+		// Get problems.
+		$problems = API::Problem()->get([
+			'output' => ['objectid', 'acknowledged', 'severity'],
+			'groupids' => array_keys($groups),
+			'hostids' => array_keys($hosts),
+			'objectids' => array_keys($triggers),
+			'search' => [
+				'name' => $filter_problem
+			],
+			'severities' => $filter_severities,
+			'acknowledged' => ($filter_ext_ack == EXTACK_OPTION_UNACK) ? false : null
+		]);
 
-						if ($filter_ext_ack == EXTACK_OPTION_UNACK) {
-							if ($trigger['priority'] > $highest_severity2[$group['groupid']]
-									&& array_key_exists($trigger['triggerid'], $triggers_unack)) {
-								$highest_severity2[$group['groupid']] = $trigger['priority'];
-							}
-						}
-						elseif ($trigger['priority'] > $highest_severity2[$group['groupid']]) {
-							$highest_severity2[$group['groupid']] = $trigger['priority'];
-						}
+		$hosts_data = [];
 
-						if (!array_key_exists($group['groupid'], $hosts_data)) {
-							$hosts_data[$group['groupid']] = [
-								'problematic' => 0,
-								'ok' => 0,
-								'lastUnack' => 0,
-								'hostids_all' => [],
-								'hostids_unack' => []
+		// Process problems.
+		foreach ($problems as $problem) {
+			$host = $hosts[$triggers[$problem['objectid']]['hosts'][0]['hostid']];
+
+			// Prepare hosts data for tables displayed in hintboxes.
+			if (!array_key_exists($host['hostid'], $hosts_data)) {
+				$hosts_data[$host['hostid']] = [
+					'host' => $host['name'],
+					'hostid' => $host['hostid'],
+					'severities' => array_fill_keys($filter_severities, 0)
 							];
 						}
 
-						if (!array_key_exists($host['hostid'], $hosts_data[$group['groupid']]['hostids_unack'])) {
-							$hosts_data[$group['groupid']]['hostids_unack'][$host['hostid']] = $host['hostid'];
-							$hosts_data[$group['groupid']]['lastUnack']++;
-						}
-					}
-				}
+			// Count number of host problems per severity.
+			$hosts_data[$host['hostid']]['severities'][$problem['severity']]++;
 
-				if (!array_key_exists($host['hostid'], $problematic_host_list)) {
-					$problematic_host_list[$host['hostid']] = [];
-					$problematic_host_list[$host['hostid']]['host'] = $host['name'];
-					$problematic_host_list[$host['hostid']]['hostid'] = $host['hostid'];
+			// Propagate problem to all host groups in which host is added.
+			foreach ($host['groups'] as $group) {
+				$groupid = $group['groupid'];
 
-					$problematic_host_list[$host['hostid']]['severities'] = [];
-
-					foreach ($filter_severities as $severity) {
-						$problematic_host_list[$host['hostid']]['severities'][$severity] = 0;
+				if (!array_key_exists($groupid, $groups)) {
+					continue;
 					}
-				}
-				$problematic_host_list[$host['hostid']]['severities'][$trigger['priority']]++;
 
-				foreach ($host['groups'] as $gnum => $group) {
-					if (!array_key_exists($group['groupid'], $highest_severity)) {
-						$highest_severity[$group['groupid']] = 0;
+				// Searches for the highest severity set for filtered problems in particular host group.
+				if ($problem['severity'] > $groups[$groupid]['highest_severity']) {
+					$groups[$groupid]['highest_severity'] = $problem['severity'];
 					}
 
-					if ($trigger['priority'] > $highest_severity[$group['groupid']]) {
-						$highest_severity[$group['groupid']] = $trigger['priority'];
+				/**
+				 * Counts:
+				 *  - problematic hosts (hosts with events in 'problem' state);
+				 *  - unacknowledged problematic hosts (hosts with unacknowledged events in 'problem' state).
+				 *
+				 * Creates a list of problematic hosts and unacknowledged problematic hosts for each host group.
+				 *
+				 * Each host need to be counted only one time in each host group.
+				 * Host name is added for sorting.
+				 */
+				if ($filter_ext_ack != EXTACK_OPTION_UNACK
+						&& !array_key_exists($host['hostid'], $groups[$groupid]['hosts_problematic_list'])) {
+					$groups[$groupid]['hosts_problematic_list'][$host['hostid']]['name'] = $host['name'];
+					$groups[$groupid]['hosts_problematic_count']++;
 					}
 
-					if (!array_key_exists($group['groupid'], $hosts_data)) {
-						$hosts_data[$group['groupid']] = [
-							'problematic' => 0,
-							'ok' => 0,
-							'lastUnack' => 0,
-							'hostids_all' => [],
-							'hostids_unack' => []
-						];
+				if ($problem['acknowledged'] == EVENT_NOT_ACKNOWLEDGED
+						&& !array_key_exists($host['hostid'], $groups[$groupid]['hosts_problematic_unack_list'])) {
+					$groups[$groupid]['hosts_problematic_unack_list'][$host['hostid']]['name'] = $host['name'];
+					$groups[$groupid]['hosts_problematic_unack_count']++;
 					}
-
-					if (!array_key_exists($host['hostid'], $hosts_data[$group['groupid']]['hostids_all'])) {
-						$hosts_data[$group['groupid']]['hostids_all'][$host['hostid']] = $host['hostid'];
-
-						/*
-						 * Display acknowledged problem triggers in "Without problems" column when filter dashboard is
-						 * enabled and is set to display "Unacknowledged only". Host and trigger must not be in
-						 * unacknowledged lists. Count as problematic host otherwise.
-						 */
-						if ($filter_ext_ack == EXTACK_OPTION_UNACK
-								&& !array_key_exists($host['hostid'], $hosts_with_unack_triggers)
-								&& !array_key_exists($trigger['triggerid'], $triggers_unack)) {
-							$hosts_data[$group['groupid']]['ok']++;
 						}
-						else {
-							$hosts_data[$group['groupid']]['problematic']++;
 						}
-					}
-				}
-			}
-		}
 
-		foreach ($hosts as $host) {
-			foreach ($host['groups'] as $group) {
-				if (!array_key_exists($group['groupid'], $groups)) {
-					continue;
-				}
+		// Sort results.
+		CArrayHelper::sort($groups, ['name']);
 
-				if (!array_key_exists('hosts', $groups[$group['groupid']])) {
-					$groups[$group['groupid']]['hosts'] = [];
+		foreach ($groups as &$group) {
+			if ($filter_ext_ack != EXTACK_OPTION_UNACK) {
+				CArrayHelper::sort($group['hosts_problematic_list'], ['name']);
 				}
-				$groups[$group['groupid']]['hosts'][$host['hostid']] = ['hostid' => $host['hostid']];
 
-				if (!array_key_exists($group['groupid'], $highest_severity)) {
-					$highest_severity[$group['groupid']] = 0;
+			CArrayHelper::sort($group['hosts_problematic_unack_list'], ['name']);
 				}
+		unset($group);
 
-				if (!array_key_exists($group['groupid'], $hosts_data)) {
-					$hosts_data[$group['groupid']] = ['problematic' => 0, 'ok' => 0, 'lastUnack' => 0];
-				}
-
-				if (!array_key_exists($host['hostid'], $problematic_host_list)) {
-					$hosts_data[$group['groupid']]['ok']++;
-				}
-			}
-		}
-
+		// Pass results to view.
 		$this->setResponse(new CControllerResponseData([
 			'name' => $this->getInput('name', $this->getDefaultHeader()),
 			'filter' => [
@@ -299,13 +238,8 @@
 				'severity_name_4' => $config['severity_name_4'],
 				'severity_name_5' => $config['severity_name_5']
 			],
-			'problematic_host_list' => $problematic_host_list,
-			'lastUnack_host_list' => $lastUnack_host_list,
-			'highest_severity2' => $highest_severity2,
-			'highest_severity' => $highest_severity,
 			'hosts_data' => $hosts_data,
 			'groups' => $groups,
-			'hosts' => $hosts,
 			'fullscreen' => $this->getInput('fullscreen', 0),
 			'user' => [
 				'debug_mode' => $this->getDebugMode()
Index: php/app/views/monitoring.widget.problemhosts.view.php
--- php/app/views/monitoring.widget.problemhosts.view.php Base (BASE)
+++ php/app/views/monitoring.widget.problemhosts.view.php Locally Modified (Based On LOCAL)
@@ -50,11 +50,11 @@
 	->setArgument('fullscreen', $data['fullscreen'] ? '1' : null);
 
 foreach ($data['groups'] as $group) {
-	if (!array_key_exists($group['groupid'], $data['hosts_data'])) {
-		continue;
-	}
+	$problematic_count_key = ($data['filter']['ext_ack'] == EXTACK_OPTION_UNACK)
+		? 'hosts_problematic_unack_count'
+		: 'hosts_problematic_count';
 
-	if ($data['filter']['hide_empty_groups'] && $data['hosts_data'][$group['groupid']]['problematic'] == 0) {
+	if ($data['filter']['hide_empty_groups'] && $group[$problematic_count_key] == 0) {
 		continue;
 	}
 
@@ -62,17 +62,23 @@
 
 	$url_group->setArgument('filter_groupids', [$group['groupid']]);
 	$url_host->setArgument('filter_groupids', [$group['groupid']]);
-	$name = new CLink($group['name'], $url_group->getUrl());
-	$group_row->addItem($name);
+	$group_name = new CLink($group['name'], $url_group->getUrl());
+	$group_row->addItem($group_name);
+
+	// Add cell for column 'Without problems'.
 	$group_row->addItem(
-		($data['hosts_data'][$group['groupid']]['ok'] != 0)
-			? $data['hosts_data'][$group['groupid']]['ok']
+		($group['hosts_total_count'] != $group[$problematic_count_key])
+			? $group['hosts_total_count'] - $group[$problematic_count_key]
 			: ''
 	);
 
+	/**
+	 * Create a CLinkAction element with hint-boxed table that contains hosts of particular host group and number of
+	 * unacknowledged problems for each host, grouped per problem severity.
+	 */
 	if ($data['filter']['ext_ack'] != EXTACK_OPTION_ALL) {
-		if ($data['hosts_data'][$group['groupid']]['lastUnack']) {
-			// Set trigger severities as table header starting from highest severity.
+		if ($group['hosts_problematic_unack_list']) {
+			// Set trigger severities as table header, ordered starting from highest severity.
 			$header = [_('Host')];
 
 			foreach (range(TRIGGER_SEVERITY_COUNT - 1, TRIGGER_SEVERITY_NOT_CLASSIFIED) as $severity) {
@@ -85,52 +91,47 @@
 
 			$popup_rows = 0;
 
-			foreach ($group['hosts'] as $host) {
-				$hostid = $host['hostid'];
+			foreach ($group['hosts_problematic_unack_list'] as $hostid => $host_name) {
+				$host = $data['hosts_data'][$hostid];
 
-				if (!array_key_exists($hostid, $data['lastUnack_host_list'])) {
-					continue;
-				}
-
-				$host_data = $data['lastUnack_host_list'][$hostid];
-
-				$url_host->setArgument('filter_hostids', [$host['hostid']]);
-				$r = new CRow();
-				$r->addItem(
+				$url_host->setArgument('filter_hostids', [$hostid]);
+				$row = new CRow();
+				$row->addItem(
 					(new CCol(
-						new CLink($host_data['host'], $url_host->getUrl())
+						new CLink($host['host'], $url_host->getUrl())
 					))->addClass(ZBX_STYLE_NOWRAP)
 				);
 
 				foreach (range(TRIGGER_SEVERITY_COUNT - 1, TRIGGER_SEVERITY_NOT_CLASSIFIED) as $severity) {
 					if (in_array($severity, $data['filter']['severities'])) {
-						$trigger_count = $data['lastUnack_host_list'][$host['hostid']]['severities'][$severity];
-
-						$r->addItem(
-							($trigger_count != 0)
-								? (new CCol($trigger_count))->addClass(getSeverityStyle($severity))
+						$row->addItem(
+							($host['severities'][$severity] != 0)
+								? (new CCol($host['severities'][$severity]))->addClass(getSeverityStyle($severity))
 								: ''
 						);
 					}
 				}
 
-				$table_inf->addRow($r);
+				$table_inf->addRow($row);
 
 				if (++$popup_rows == ZBX_WIDGET_ROWS) {
 					break;
 				}
 			}
-			$lastUnack_count = (new CLinkAction($data['hosts_data'][$group['groupid']]['lastUnack']))
-				->setHint($table_inf);
+
+			$last_unack_count = (new CLinkAction($group['hosts_problematic_unack_count']))->setHint($table_inf);
 		}
 		else {
-			$lastUnack_count = 0;
+			$last_unack_count = null;
 		}
 	}
 
-	// if hostgroup contains problematic hosts, hint should be built
-	if ($data['hosts_data'][$group['groupid']]['problematic']) {
-		// Set trigger severities as table header starting from highest severity.
+	/**
+	 * Create a CLinkAction element with hint-boxed table that contains hosts of particular host group and number of all
+	 * problems for each host, grouped per problem severity.
+	 */
+	if ($data['filter']['ext_ack'] != EXTACK_OPTION_UNACK && $group['hosts_problematic_count'] != 0) {
+		// Set trigger severities as table header, ordered starting from highest severity.
 		$header = [_('Host')];
 
 		foreach (range(TRIGGER_SEVERITY_COUNT - 1, TRIGGER_SEVERITY_NOT_CLASSIFIED) as $severity) {
@@ -143,18 +144,12 @@
 
 		$popup_rows = 0;
 
-		foreach ($group['hosts'] as $host) {
-			$hostid = $host['hostid'];
+		foreach ($group['hosts_problematic_list'] as $hostid => $host_name) {
+			$host_data = $data['hosts_data'][$hostid];
 
-			if (!array_key_exists($hostid, $data['problematic_host_list'])) {
-				continue;
-			}
-
-			$host_data = $data['problematic_host_list'][$hostid];
-
-			$url_host->setArgument('filter_hostids', [$host['hostid']]);
-			$r = new CRow();
-			$r->addItem(
+			$url_host->setArgument('filter_hostids', [$hostid]);
+			$table_inf_row = new CRow();
+			$table_inf_row->addItem(
 				(new CCol(
 					new CLink($host_data['host'], $url_host->getUrl())
 				))->addClass(ZBX_STYLE_NOWRAP)
@@ -162,78 +157,64 @@
 
 			foreach (range(TRIGGER_SEVERITY_COUNT - 1, TRIGGER_SEVERITY_NOT_CLASSIFIED) as $severity) {
 				if (in_array($severity, $data['filter']['severities'])) {
-					$trigger_count = $data['problematic_host_list'][$host['hostid']]['severities'][$severity];
-
-					$r->addItem(
-						($trigger_count != 0)
-							? (new CCol($trigger_count))->addClass(getSeverityStyle($severity))
+					$table_inf_row->addItem(
+						($host_data['severities'][$severity] != 0)
+							? (new CCol($host_data['severities'][$severity]))->addClass(getSeverityStyle($severity))
 							: ''
 					);
 				}
 			}
 
-			$table_inf->addRow($r);
+			$table_inf->addRow($table_inf_row);
 
 			if (++$popup_rows == ZBX_WIDGET_ROWS) {
 				break;
 			}
 		}
-		$problematic_count = (new CLinkAction($data['hosts_data'][$group['groupid']]['problematic']))
-			->setHint($table_inf);
+
+		$problematic_count = (new CLinkAction($group['hosts_problematic_count']))->setHint($table_inf);
 	}
-	else {
-		$problematic_count = 0;
-	}
 
+	// Add 'With problems' column with ext_ack specific content.
 	switch ($data['filter']['ext_ack']) {
 		case EXTACK_OPTION_ALL:
-			if ($data['hosts_data'][$group['groupid']]['problematic'] != 0) {
+			if ($group['hosts_problematic_count'] != 0) {
 				$group_row->addItem((new CCol($problematic_count))
-					->addClass(getSeverityStyle($data['highest_severity'][$group['groupid']]))
+					->addClass(getSeverityStyle($group['highest_severity']))
 				);
 			}
 			else {
 				$group_row->addItem('');
 			}
-			$group_row->addItem(
-				$data['hosts_data'][$group['groupid']]['problematic'] + $data['hosts_data'][$group['groupid']]['ok']
-			);
 			break;
 
-		case EXTACK_OPTION_UNACK:
-			if ($data['hosts_data'][$group['groupid']]['lastUnack'] != 0) {
-				$group_row->addItem((new CCol($lastUnack_count))
-					->addClass(getSeverityStyle(
-						array_key_exists($group['groupid'], $data['highest_severity2'])
-							? $data['highest_severity2'][$group['groupid']]
-							: TRIGGER_SEVERITY_NOT_CLASSIFIED
-					))
+		case EXTACK_OPTION_BOTH:
+			if ($group['hosts_problematic_count'] != 0) {
+				$unack_span = $last_unack_count ? [$last_unack_count, ' '._('of').' '] : null;
+				$group_row->addItem((new CCol([$unack_span, $problematic_count]))
+					->addClass(getSeverityStyle($group['highest_severity']))
 				);
 			}
 			else {
 				$group_row->addItem('');
 			}
-			$group_row->addItem(
-				$data['hosts_data'][$group['groupid']]['lastUnack'] + $data['hosts_data'][$group['groupid']]['ok']
-			);
 			break;
 
-		case EXTACK_OPTION_BOTH:
-			if ($data['hosts_data'][$group['groupid']]['problematic'] != 0) {
-				$unackspan = $lastUnack_count ? [$lastUnack_count, ' '._('of').' '] : null;
-				$group_row->addItem((new CCol([$unackspan, $problematic_count]))
-					->addClass(getSeverityStyle($data['highest_severity'][$group['groupid']]))
+		case EXTACK_OPTION_UNACK:
+			if ($group['hosts_problematic_unack_count'] != 0) {
+				$group_row->addItem((new CCol($last_unack_count))
+					->addClass(getSeverityStyle($group['highest_severity']))
 				);
 			}
 			else {
 				$group_row->addItem('');
 			}
-			$group_row->addItem(
-				$data['hosts_data'][$group['groupid']]['problematic'] + $data['hosts_data'][$group['groupid']]['ok']
-			);
 			break;
 	}
 
+	// Add 'Total' column.
+	$group_row->addItem($group['hosts_total_count']);
+
 	$table->addRow($group_row);
 }
 
Index: php/include/hostgroups.inc.php
--- php/include/hostgroups.inc.php Base (BASE)
+++ php/include/hostgroups.inc.php Locally Modified (Based On LOCAL)
@@ -192,7 +192,7 @@
  * Get sub-groups of selected host groups.
  *
  * @param array $groupids
- * @param array $ms_groups  [OUT] the list of groups for multiselect
+ * @param array $ms_groups [OUT] the list of groups for multiselect
  *
  * @return array
  */
