1<?php
2/*
3** Zabbix
4** Copyright (C) 2001-2021 Zabbix SIA
5**
6** This program is free software; you can redistribute it and/or modify
7** it under the terms of the GNU General Public License as published by
8** the Free Software Foundation; either version 2 of the License, or
9** (at your option) any later version.
10**
11** This program is distributed in the hope that it will be useful,
12** but WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14** GNU General Public License for more details.
15**
16** You should have received a copy of the GNU General Public License
17** along with this program; if not, write to the Free Software
18** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19**/
20
21
22/**
23 * Converter for converting import data from 1.8 to 2.0.
24 */
25class C10ImportConverter extends CConverter {
26
27	/**
28	 * Converter used for converting simple check item keys.
29	 *
30	 * @var CConverter
31	 */
32	protected $itemKeyConverter;
33
34	/**
35	 * Converter used for converting trigger expressions.
36	 *
37	 * @var CConverter
38	 */
39	protected $triggerConverter;
40
41	public function __construct() {
42		$this->itemKeyConverter = new C10ItemKeyConverter();
43		$this->triggerConverter = new C10TriggerConverter();
44	}
45
46	public function convert($value) {
47		$content = $value['zabbix_export'];
48
49		$content['version'] = '2.0';
50		$content = $this->convertTime($content);
51
52		$content = $this->convertDependencies($content);
53		$content = $this->separateTemplatesFromHosts($content);
54		$content = $this->convertHosts($content);
55		$content = $this->convertTemplates($content);
56
57		$content = $this->convertSysmaps($content);
58
59		$content = $this->filterDuplicateGroups($content);
60		$content = $this->filterDuplicateTriggers($content);
61		$content = $this->filterDuplicateGraphs($content);
62
63		$value['zabbix_export'] = $content;
64
65		return $value;
66	}
67
68	/**
69	 * Convert the date and time elements.
70	 *
71	 * @param array $content
72	 *
73	 * @return array
74	 */
75	protected function convertTime(array $content) {
76		if (array_key_exists('date', $content) && array_key_exists('time', $content)) {
77			list($day, $month, $year) = explode('.', $content['date']);
78			list($hours, $minutes) = explode('.', $content['time']);
79			$content['date'] = date(DATE_TIME_FORMAT_SECONDS_XML, mktime($hours, $minutes, 0, $month, $day, $year));
80		}
81
82		unset($content['time']);
83
84		return $content;
85	}
86
87	/**
88	 * Separate templates and their elements from other hosts into the "templates" array.
89	 *
90	 * @param array $content
91	 *
92	 * @return array
93	 */
94	protected function separateTemplatesFromHosts(array $content) {
95		if (!isset($content['hosts']) || !$content['hosts']) {
96			return $content;
97		}
98
99		$templates = [];
100		foreach ($content['hosts'] as $i => $host) {
101			// skip hosts
102			if (isset($host['status']) && $host['status'] != HOST_STATUS_TEMPLATE) {
103				continue;
104			}
105
106			$template = [];
107			foreach (['name', 'groups', 'items', 'templates', 'triggers', 'graphs', 'macros'] as $key) {
108				if (isset($host[$key])) {
109					$template[$key] = $host[$key];
110				}
111			}
112
113			$templates[] = $template;
114
115			unset($content['hosts'][$i]);
116		}
117
118		if ($templates) {
119			$content['templates'] = $templates;
120
121			// reset host keys
122			$content['hosts'] = array_values($content['hosts']);
123		}
124
125		return $content;
126	}
127
128	/**
129	 * Convert host elements.
130	 *
131	 * @param array $content
132	 *
133	 * @return array
134	 */
135	protected function convertHosts(array $content) {
136		if (!isset($content['hosts']) || !$content['hosts']) {
137			return $content;
138		}
139
140		foreach ($content['hosts'] as &$host) {
141			$host['host'] = $host['name'];
142			$host = $this->convertHostInterfaces($host);
143			$host = $this->convertHostProfiles($host);
144			$host = $this->convertHostApplications($host);
145			$host = $this->convertHostItems($host);
146			$host = $this->convertHostTriggers($host, $host['host']);
147			$host = $this->convertHostGraphs($host, $host['host']);
148			$host = $this->convertHostMacros($host);
149			$host = $this->convertProxy($host);
150
151			$host = $this->wrapChildren($host, 'templates', 'name');
152			$host = $this->wrapChildren($host, 'groups', 'name');
153
154			unset($host['useipmi']);
155			unset($host['useip']);
156			unset($host['ip']);
157			unset($host['dns']);
158			unset($host['port']);
159			unset($host['ipmi_ip']);
160			unset($host['ipmi_port']);
161			unset($host['host_profile']);
162			unset($host['host_profiles_ext']);
163		}
164		unset($host);
165
166		$content = $this->mergeTo($content['hosts'], $content, 'groups');
167		$content = $this->mergeTo($content['hosts'], $content, 'triggers');
168		$content = $this->mergeTo($content['hosts'], $content, 'graphs');
169		foreach ($content['hosts'] as &$host) {
170			unset($host['triggers']);
171			unset($host['graphs']);
172		}
173		unset($host);
174
175		return $content;
176	}
177
178	/**
179	 * Convert template elements.
180	 *
181	 * @param array $content
182	 *
183	 * @return array
184	 */
185	protected function convertTemplates(array $content) {
186		if (!isset($content['templates'])) {
187			return $content;
188		}
189
190		foreach ($content['templates'] as &$template) {
191			$template['template'] = $template['name'];
192			$template = $this->convertTemplateItem($template);
193			$template = $this->convertHostApplications($template);
194			$template = $this->convertHostItems($template);
195			$template = $this->convertHostTriggers($template, $template['template']);
196			$template = $this->convertHostGraphs($template, $template['template']);
197			$template = $this->convertHostMacros($template);
198
199			$template = $this->wrapChildren($template, 'templates', 'name');
200			$template = $this->wrapChildren($template, 'groups', 'name');
201		}
202		unset($template);
203
204		$content = $this->mergeTo($content['templates'], $content, 'groups');
205		$content = $this->mergeTo($content['templates'], $content, 'triggers');
206		$content = $this->mergeTo($content['templates'], $content, 'graphs');
207		foreach ($content['templates'] as &$host) {
208			unset($host['triggers']);
209			unset($host['graphs']);
210		}
211		unset($host);
212
213		return $content;
214	}
215
216	/**
217	 * Create host interfaces from the host properties and items and add them to the "host" element.
218	 *
219	 * @param array $host
220	 *
221	 * @return array
222	 */
223	protected function convertHostInterfaces(array $host) {
224		$interfaces = [];
225		$i = 0;
226
227		// create an agent interface from the host properties
228		if (isset($host['useip']) && isset($host['ip']) && isset($host['dns']) && isset($host['port'])) {
229			$agentInterface = [
230				'type' => (string) INTERFACE_TYPE_AGENT,
231				'useip' => $host['useip'],
232				'ip' => $host['ip'],
233				'dns' => $host['dns'],
234				'port' => $host['port'],
235				'default' => (string) INTERFACE_PRIMARY,
236				'interface_ref' => 'if'.$i
237			];
238			$interfaces[] = $agentInterface;
239			$i++;
240		}
241
242		$hasIpmiItem = false;
243		$snmpItems = [];
244
245		if (isset($host['items']) && $host['items']) {
246			foreach ($host['items'] as $item) {
247				if (!isset($item['type'])) {
248					continue;
249				}
250
251				if ($item['type'] == ITEM_TYPE_IPMI) {
252					$hasIpmiItem = true;
253				}
254				if ($item['type'] == ITEM_TYPE_SNMPV1 || $item['type'] == ITEM_TYPE_SNMPV2C
255						|| $item['type'] == ITEM_TYPE_SNMPV3) {
256					$snmpItems[] = $item;
257				}
258			}
259
260			// if a least one IPMI item exists on a host, create an IPMI interface
261			if ($hasIpmiItem) {
262				$ipmiInterface = [
263					'type' => (string) INTERFACE_TYPE_IPMI,
264					'useip' => (string) INTERFACE_USE_IP,
265					'ip' => (array_key_exists('ipmi_ip', $host) && $host['ipmi_ip'] !== '')
266						? $host['ipmi_ip'] : $host['ip'],
267					'dns' => '',
268					'port' => (array_key_exists('ipmi_port', $host) && $host['ipmi_port'] !== '')
269						? $host['ipmi_port'] : '623',
270					'default' => (string) INTERFACE_PRIMARY,
271					'interface_ref' => 'if'.$i
272				];
273				$interfaces[] = $ipmiInterface;
274				$i++;
275			}
276
277			// if SNMP item exist, create an SNMP interface for each SNMP item port.
278			if ($snmpItems) {
279				$snmpInterfaces = [];
280				foreach ($snmpItems as $item) {
281					if (!isset($item['snmp_port']) || isset($snmpInterfaces[$item['snmp_port']])) {
282						continue;
283					}
284
285					$snmpInterface = [
286						'type' => (string) INTERFACE_TYPE_SNMP,
287						'useip' => $host['useip'],
288						'ip' => $host['ip'],
289						'dns' => $host['dns'],
290						'port' => $item['snmp_port'],
291						'default' => (count($snmpInterfaces)) ? (string) INTERFACE_SECONDARY : (string) INTERFACE_PRIMARY,
292						'interface_ref' => 'if'.$i
293					];
294					$snmpInterfaces[$item['snmp_port']] = $snmpInterface;
295					$interfaces[] = $snmpInterface;
296					$i++;
297				}
298			}
299		}
300
301		if ($interfaces) {
302			$host['interfaces'] = $interfaces;
303		}
304
305		// map items to new interfaces
306		if (isset($host['items']) && $host['items']) {
307			foreach ($host['items'] as &$item) {
308				if (!isset($item['type'])) {
309					continue;
310				}
311
312				$interfaceType = itemTypeInterface($item['type']);
313				switch ($interfaceType) {
314					case INTERFACE_TYPE_AGENT:
315					case INTERFACE_TYPE_ANY:
316						$item['interface_ref'] = $agentInterface['interface_ref'];
317
318						break;
319					case INTERFACE_TYPE_IPMI:
320						$item['interface_ref'] = $ipmiInterface['interface_ref'];
321
322						break;
323					case INTERFACE_TYPE_SNMP:
324						if (isset($item['snmp_port'])) {
325							$item['interface_ref'] = $snmpInterfaces[$item['snmp_port']]['interface_ref'];
326						}
327
328						break;
329				}
330
331				unset($item['snmp_port']);
332			}
333			unset($item);
334		}
335
336		return $host;
337	}
338
339	/**
340	 * Convert host "host_profile" and "host_profiles_ext" elements and calculate "inventory_mode".
341	 *
342	 * @param array $host
343	 *
344	 * @return array
345	 */
346	protected function convertHostProfiles(array $host) {
347		$host['inventory'] = ['inventory_mode' => (string) HOST_INVENTORY_DISABLED];
348
349		// rename and merge profile fields
350		if (array_key_exists('host_profile', $host)) {
351			foreach ($host['host_profile'] as $key => $value) {
352				$host['inventory'][$this->getNewProfileName($key)] = $value;
353			}
354			$host['inventory']['inventory_mode'] = (string) HOST_INVENTORY_MANUAL;
355		}
356
357		if (array_key_exists('host_profiles_ext', $host)) {
358			foreach ($host['host_profiles_ext'] as $key => $value) {
359				$key = $this->getNewProfileName($key);
360
361				// if renaming results in a duplicate inventory field, concatenate them
362				// this is the case with "notes" and "device_notes"
363				if (array_key_exists($key, $host['inventory']) && $host['inventory'][$key] !== '') {
364					$host['inventory'][$key] .= "\r\n\r\n".$value;
365				}
366				else {
367					$host['inventory'][$key] = $value;
368				}
369			}
370			$host['inventory']['inventory_mode'] = (string) HOST_INVENTORY_MANUAL;
371		}
372
373		return $host;
374	}
375
376	/**
377	 * Map an old profile key name to the new inventory key name.
378	 *
379	 * @param string $key
380	 *
381	 * @return string
382	 */
383	protected function getNewProfileName($key) {
384		$map = [
385			'devicetype' => 'type',
386			'serialno' => 'serialno_a',
387			'macaddress' => 'macaddress_a',
388			'hardware' => 'hardware_full',
389			'software' => 'software_full',
390			'device_type' => 'type_full',
391			'device_alias' => 'alias',
392			'device_os' => 'os_full',
393			'device_os_short' => 'os_short',
394			'device_serial' => 'serialno_b',
395			'device_tag' => 'asset_tag',
396			'ip_macaddress' => 'macaddress_b',
397			'device_hardware' => 'hardware',
398			'device_software' => 'software',
399			'device_app_01' => 'software_app_a',
400			'device_app_02' => 'software_app_b',
401			'device_app_03' => 'software_app_c',
402			'device_app_04' => 'software_app_d',
403			'device_app_05' => 'software_app_e',
404			'device_chassis' => 'chassis',
405			'device_model' => 'model',
406			'device_hw_arch' => 'hw_arch',
407			'device_vendor' => 'vendor',
408			'device_contract' => 'contract_number',
409			'device_who' => 'installer_name',
410			'device_status' => 'deployment_status',
411			'device_url_1' => 'url_a',
412			'device_url_2' => 'url_b',
413			'device_url_3' => 'url_c',
414			'device_networks' => 'host_networks',
415			'ip_subnet_mask' => 'host_netmask',
416			'ip_router' => 'host_router',
417			'oob_subnet_mask' => 'oob_netmask',
418			'date_hw_buy' => 'date_hw_purchase',
419			'site_street_1' => 'site_address_a',
420			'site_street_2' => 'site_address_b',
421			'site_street_3' => 'site_address_c',
422			'poc_1_phone_1' => 'poc_1_phone_a',
423			'poc_1_phone_2' => 'poc_1_phone_b',
424			'poc_2_phone_1' => 'poc_2_phone_a',
425			'poc_2_phone_2' => 'poc_2_phone_b',
426			'device_notes' => 'notes'
427		];
428
429		return array_key_exists($key, $map) ? $map[$key] : $key;
430	}
431
432	/**
433	 * Filters duplicate host groups from the content.
434	 *
435	 * @param array $content
436	 *
437	 * @return array
438	 */
439	protected function filterDuplicateGroups(array $content) {
440		if (!isset($content['groups'])) {
441			return $content;
442		}
443
444		$groups = [];
445
446		foreach ($content['groups'] as $group) {
447			$groups[$group['name']] = $group;
448		}
449
450		$content['groups'] = array_values($groups);
451
452		return $content;
453	}
454
455	/**
456	 * Converts triggers elements.
457	 *
458	 * @param array 	$host
459	 * @param string 	$hostName 	technical name of the host that the triggers were imported under
460	 *
461	 * @return array
462	 */
463	protected function convertHostTriggers(array $host, $hostName) {
464		if (!isset($host['triggers']) || !$host['triggers']) {
465			return $host;
466		}
467
468		foreach ($host['triggers'] as &$trigger) {
469			$trigger = CArrayHelper::renameKeys($trigger, ['description' => 'name', 'comments' => 'description']);
470			$trigger = $this->convertTriggerExpression($trigger, $hostName);
471		}
472		unset($trigger);
473
474		return $host;
475	}
476
477	/**
478	 * Allocate the dependencies from the root element to the trigger elements and convert them to a new format.
479	 *
480	 * Dependencies, that cannot be resolved are skipped.
481	 *
482	 * @param array $content
483	 *
484	 * @return array
485	 */
486	protected function convertDependencies(array $content) {
487		// we cannot import dependencies if hosts are missing
488		if (!isset($content['dependencies']) || !$content['dependencies'] || !isset($content['hosts'])) {
489			unset($content['dependencies']);
490
491			return $content;
492		}
493
494		// build a description-expression trigger index with references to the triggers in the content
495		$descriptionExpressionIndex = [];
496		foreach ($content['hosts'] as $hostKey => $host) {
497			if (!isset($host['triggers']) || !$host['triggers']) {
498				continue;
499			}
500
501			foreach ($host['triggers'] as $triggerKey => $trigger) {
502				$descriptionExpressionIndex[$trigger['description']][$trigger['expression']][] =
503					&$content['hosts'][$hostKey]['triggers'][$triggerKey];
504			}
505		}
506
507		$hosts = zbx_toHash($content['hosts'], 'name');
508
509		foreach ($content['dependencies'] as $dependency) {
510			list($sourceHost, $sourceDescription) = explode(':', $dependency['description'], 2);
511			unset($dependency['description']);
512
513			// if one of the hosts is missing from the data or doesn't have any triggers, skip this dependency
514			if (!isset($hosts[$sourceHost]) || !isset($hosts[$sourceHost]['triggers'])) {
515				continue;
516			}
517
518			foreach ($dependency as $depends) {
519				list($targetHost, $targetDescription) = explode(':', $depends, 2);
520
521				// if one of the hosts is missing from the data or doesn't have any triggers, skip this dependency
522				if (!isset($hosts[$targetHost]) || !isset($hosts[$targetHost]['triggers'])) {
523					continue;
524				}
525
526				// find the target trigger
527				// use the first trigger with the same description
528				$targetTrigger = null;
529				foreach ($hosts[$targetHost]['triggers'] as $trigger) {
530					if ($trigger['description'] === $targetDescription) {
531						$targetTrigger = $trigger;
532
533						break;
534					}
535				}
536
537				// if the target trigger wasn't found - skip this dependency
538				if (!$targetTrigger) {
539					continue;
540				}
541
542				// find the source trigger and add the dependencies to all of the copies of the trigger
543				foreach ($hosts[$targetHost]['triggers'] as $trigger) {
544					if ($trigger['description'] === $sourceDescription) {
545						// if the source trigger is not present in the data - skip this dependency
546						if (!isset($descriptionExpressionIndex[$trigger['description']])
547								|| !isset($descriptionExpressionIndex[$trigger['description']][$trigger['expression']])) {
548
549							continue 2;
550						}
551
552						// working with references to triggers in the content here
553						foreach ($descriptionExpressionIndex[$trigger['description']][$trigger['expression']] as &$trigger) {
554							$trigger['dependencies'][] = [
555								'name' => $targetTrigger['description'],
556								'expression' => $this->triggerConverter->convert($targetTrigger['expression'])
557							];
558						}
559						unset($trigger);
560					}
561				}
562			}
563		}
564
565		$content['hosts'] = array_values($hosts);
566		unset($content['dependencies']);
567
568		return $content;
569	}
570
571	/**
572	 * Filters duplicate triggers from the array and returns the content with unique triggers.
573	 *
574	 * @param array $content
575	 *
576	 * @return array
577	 */
578	protected function filterDuplicateTriggers(array $content) {
579		if (!isset($content['triggers'])) {
580			return $content;
581		}
582
583		$existingTriggers = [];
584
585		$filteredTriggers = [];
586		foreach ($content['triggers'] as $trigger) {
587			$name = $trigger['name'];
588			$expression = $trigger['expression'];
589
590			if (isset($existingTriggers[$name]) && isset($existingTriggers[$name][$expression])) {
591				continue;
592			}
593
594			$filteredTriggers[] = $trigger;
595			$existingTriggers[$name][$expression] = true;
596		}
597
598		$content['triggers'] = $filteredTriggers;
599
600		return $content;
601	}
602
603	/**
604	 * Convert trigger expression and replace host macros.
605	 *
606	 * @param array 	$trigger
607	 * @param string 	$hostName	technical name of the host that the trigger was imported under
608	 *
609	 * @return string
610	 */
611	protected function convertTriggerExpression(array $trigger, $hostName) {
612		$trigger['expression'] = $this->triggerConverter->convert($trigger['expression']);
613
614		// replace host macros with the host name
615		// not sure why this is required, but this has been preserved from when refactoring CXmlImport18
616		$trigger['expression'] = str_replace('{HOSTNAME}', $hostName, $trigger['expression']);
617		$trigger['expression'] = str_replace('{HOST.HOST}', $hostName, $trigger['expression']);
618
619		return $trigger;
620	}
621
622	/**
623	 * Convert application from items.
624	 *
625	 * @param array $host
626	 *
627	 * @return array
628	 */
629	protected function convertHostApplications(array $host) {
630		if (!isset($host['items']) || !$host['items']) {
631			return $host;
632		}
633
634		foreach ($host['items'] as $item) {
635			if (isset($item['applications']) && $item['applications'] !== '') {
636				foreach ($item['applications'] as $application) {
637					$host['applications'][] = ['name' => $application];
638				}
639			}
640		}
641
642		return $host;
643	}
644
645	/**
646	 * Convert item elements.
647	 *
648	 * @param array $host
649	 *
650	 * @return array
651	 */
652	protected function convertHostItems(array $host) {
653		if (!isset($host['items']) || !$host['items']) {
654			return $host;
655		}
656
657		foreach ($host['items'] as &$item) {
658			$item = CArrayHelper::renameKeys($item, ['trapper_hosts' => 'allowed_hosts']);
659			$item['name'] = $item['description'];
660
661			// convert simple check keys
662			$item['key'] = $this->itemKeyConverter->convert($item['key']);
663
664			$item = $this->wrapChildren($item, 'applications', 'name');
665
666			$item = $this->convertItemValueMap($item);
667
668			// Add tag inventory_link.
669			$item['inventory_link'] = '';
670			$item['snmpv3_contextname'] = '';
671			$item['snmpv3_authprotocol'] = '';
672			$item['snmpv3_privprotocol'] = '';
673
674			unset($item['lastlogsize']);
675		}
676		unset($item);
677
678		return $host;
679	}
680
681	/**
682	 * Convert graph elements.
683	 *
684	 * @param array 	$host
685	 * @param string 	$hostName	technical name of the host that the graphs were imported under
686	 *
687	 * @return array
688	 */
689	protected function convertHostGraphs(array $host, $hostName) {
690		if (!isset($host['graphs']) || !$host['graphs']) {
691			return $host;
692		}
693
694		foreach ($host['graphs'] as &$graph) {
695			$graph = CArrayHelper::renameKeys($graph, [
696				'graphtype' => 'type',
697				'graph_elements' => 'graph_items',
698				'ymin_type' => 'ymin_type_1',
699				'ymax_type' => 'ymax_type_1',
700				'ymin_item_key' => 'ymin_item_1',
701				'ymax_item_key' => 'ymax_item_1'
702			]);
703			$graph = $this->convertGraphItemReference($graph, 'ymin_item_1');
704			$graph = $this->convertGraphItemReference($graph, 'ymax_item_1');
705
706			foreach ($graph['graph_items'] as &$graphItem) {
707				$graphItem = $this->convertGraphItemReference($graphItem, 'item', $hostName);
708
709				unset($graphItem['periods_cnt']);
710			}
711			unset($graphItem);
712
713			$graph['graph_items'] = array_values($graph['graph_items']);
714		}
715		unset($graph);
716
717		return $host;
718	}
719
720	/**
721	 * Convert item references used in graphs.
722	 *
723	 * @param array 		$array		source array
724	 * @param string		$key		property under which the reference is stored
725	 * @param string|null 	$host_name	if set to some host name, host macros will be resolved into this host
726	 *
727	 * @return array
728	 */
729	protected function convertGraphItemReference(array $array, $key, $host_name = null) {
730		if ($array[$key] === '') {
731			$array[$key] = [];
732		}
733		else {
734			list ($host, $item_key) = explode(':', $array[$key], 2);
735
736			// replace host macros with the host name
737			// not sure why this is required, but this has been preserved from when refactoring CXmlImport18
738			if ($host_name !== null && ($host === '{HOSTNAME}' || $host === '{HOST.HOST}')) {
739				$host = $host_name;
740			}
741
742			$array[$key] = ['host' => $host, 'key' => $this->itemKeyConverter->convert($item_key)];
743		}
744
745		return $array;
746	}
747
748	/**
749	 * Filters duplicate graphs from the array and returns the content with unique graphs.
750	 *
751	 * Graphs are assumed identical if their names and items are identical.
752	 *
753	 * @param array $content
754	 *
755	 * @return array
756	 */
757	protected function filterDuplicateGraphs(array $content) {
758		if (!isset($content['graphs'])) {
759			return $content;
760		}
761
762		$existingGraphs = [];
763
764		$filteredGraphs = [];
765		foreach ($content['graphs'] as $graph) {
766			$name = $graph['name'];
767			$graphItems = $graph['graph_items'];
768
769			if (isset($existingGraphs[$name])) {
770				foreach ($existingGraphs[$name] as $existingGraphItems) {
771					if ($graphItems == $existingGraphItems) {
772						continue 2;
773					}
774				}
775			}
776
777			$filteredGraphs[] = $graph;
778
779			$existingGraphs[$name][] = $graphItems;
780		}
781
782		$content['graphs'] = $filteredGraphs;
783
784		return $content;
785	}
786
787	/**
788	 * Converts host macro elements.
789	 *
790	 * @param array 	$host
791	 *
792	 * @return array
793	 */
794	protected function convertHostMacros(array $host) {
795		if (!isset($host['macros']) || !$host['macros']) {
796			return $host;
797		}
798
799		foreach ($host['macros'] as &$macro) {
800			$macro = CArrayHelper::renameKeys($macro, ['name' => 'macro']);
801		}
802		unset($macro);
803
804		return $host;
805	}
806
807	/**
808	 * Convert map elements.
809	 *
810	 * @param array $content
811	 *
812	 * @return array
813	 */
814	protected function convertSysmaps(array $content) {
815		if (!isset($content['sysmaps']) || !$content['sysmaps']) {
816			return $content;
817		}
818
819		$content = CArrayHelper::renameKeys($content, ['sysmaps' => 'maps']);
820		foreach ($content['maps'] as &$map) {
821			if (isset($map['selements']) && $map['selements']) {
822				foreach ($map['selements'] as &$selement) {
823					$selement = CArrayHelper::renameKeys($selement, [
824						'elementid' => 'element',
825						'iconid_off' => 'icon_off',
826						'iconid_on' => 'icon_on',
827						'iconid_disabled' => 'icon_disabled',
828						'iconid_maintenance' => 'icon_maintenance'
829					]);
830
831					if (isset($selement['elementtype']) && $selement['elementtype'] == SYSMAP_ELEMENT_TYPE_TRIGGER) {
832						$selement['element']['expression'] = $this->triggerConverter->convert(
833							$selement['element']['expression']
834						);
835
836						unset($selement['element']['host']);
837					}
838
839					unset($selement['iconid_unknown']);
840				}
841				unset($selement);
842			}
843
844			if (isset($map['links']) && $map['links']) {
845				foreach ($map['links'] as &$link) {
846					if (isset($link['linktriggers']) && $link['linktriggers']) {
847						foreach ($link['linktriggers'] as &$linkTrigger) {
848							$linkTrigger = CArrayHelper::renameKeys($linkTrigger, ['triggerid' => 'trigger']);
849							$linkTrigger['trigger']['expression'] = $this->triggerConverter->convert(
850								$linkTrigger['trigger']['expression']
851							);
852
853							unset($linkTrigger['trigger']['host']);
854						}
855						unset($linkTrigger);
856					}
857				}
858				unset($link);
859			}
860
861			if (!array_key_exists('backgroundid', $map)) {
862				$map['backgroundid'] = '';
863			}
864
865			$map = CArrayHelper::renameKeys($map, ['backgroundid' => 'background']);
866		}
867		unset($map);
868
869		return $content;
870	}
871
872	/**
873	 * Merges all of the values from each element of $source stored in the $key property to the $key property of $target.
874	 *
875	 * @param array $source
876	 * @param array $target
877	 * @param string $key
878	 *
879	 * @return array    $target array with the new values
880	 */
881	protected function mergeTo(array $source, array $target, $key) {
882		$values = (isset($target[$key])) ? $target[$key] : [];
883
884		foreach ($source as $sourceItem) {
885			if (!isset($sourceItem[$key]) || !$sourceItem[$key]) {
886				continue;
887			}
888
889			foreach ($sourceItem[$key] as $value) {
890				$values[] = $value;
891			}
892
893		}
894
895		if ($values) {
896			$target[$key] = $values;
897		}
898
899		return $target;
900	}
901
902	/**
903	 * Adds a $wrapperKey property for each element of $key in $array and moves it's value to the new property.
904	 *
905	 * @param array $array
906	 * @param string $key
907	 * @param string $wrapperKey
908	 *
909	 * @return array
910	 */
911	protected function wrapChildren(array $array, $key, $wrapperKey) {
912		if (array_key_exists($key, $array)) {
913			foreach ($array[$key] as &$content) {
914				$content = [$wrapperKey => $content];
915			}
916			unset($content);
917		}
918
919		return $array;
920	}
921
922	/**
923	 * Convert old proxy format to new proxy format.
924	 *
925	 * @param array $host  Import data.
926	 *
927	 * @return array
928	 */
929	protected function convertProxy(array $host) {
930		if (!array_key_exists('proxy_hostid', $host)) {
931			$host['proxy_hostid'] = '';
932		}
933
934		$host['proxy']['name'] = $host['proxy_hostid'];
935		unset($host['proxy_hostid']);
936
937		return $host;
938	}
939
940	/**
941	 * Convert valuemap for items.
942	 *
943	 * @param array $item  Import data.
944	 *
945	 * @return array
946	 */
947	protected function convertItemValueMap(array $item) {
948		$item['valuemap'] = [];
949		if (array_key_exists('valuemapid', $item)) {
950			$item['valuemap']['name'] = $item['valuemapid'];
951			unset($item['valuemapid']);
952		}
953
954		return $item;
955	}
956
957	/**
958	 * Add new tag port to template items.
959	 *
960	 * @param array $template  Import data.
961	 *
962	 * @return array
963	 */
964	protected function convertTemplateItem(array $template) {
965		if (array_key_exists('items', $template)) {
966			foreach ($template['items'] as &$item) {
967				$item['port'] = '';
968				unset($item['snmp_port']);
969			}
970		}
971
972		return $template;
973	}
974}
975