1<?php
2/*****************************************************************************
3 *
4 * NagVisObject.php - Abstract class of an object in NagVis with all necessary
5 *                  information which belong to the object handling in NagVis
6 *
7 * Copyright (c) 2004-2016 NagVis Project (Contact: info@nagvis.org)
8 *
9 * License:
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *****************************************************************************/
25
26/**
27 * @author	Lars Michelsen <lm@larsmichelsen.com>
28 */
29class NagVisObject {
30    protected $conf = array();
31
32    protected $object_id;
33    protected $x;
34    protected $y;
35    protected $z;
36    protected $icon;
37    protected $url;
38    protected $url_target;
39
40    protected $view_type;
41    protected $hover_menu;
42    protected $hover_childs_show;
43    protected $hover_childs_sort;
44    protected $hover_childs_order;
45    protected $hover_childs_limit;
46    protected $label_show;
47
48    protected static $sSortOrder = 'asc';
49    protected static $stateWeight = null;
50    private static $arrDenyKeys = null;
51
52    public function __construct() {}
53
54    /**
55     * Get method for all options
56     *
57     * @return	Value  Value of the given option
58     * @author	Lars Michelsen <lm@larsmichelsen.com>
59     */
60    public function get($option) {
61        return $this->{$option};
62    }
63
64    /**
65     * Get method for x coordinate of the object
66     *
67     * @return	Integer		x coordinate on the map
68     * @author	Lars Michelsen <lm@larsmichelsen.com>
69     */
70    public function getX() {
71        return $this->x;
72    }
73
74    /**
75     * Get method for y coordinate of the object
76     *
77     * @return	Integer		y coordinate on the map
78     * @author	Lars Michelsen <lm@larsmichelsen.com>
79     */
80    public function getY() {
81        return $this->y;
82    }
83
84    /**
85     * Get method for z coordinate of the object
86     *
87     * @return	Integer		z coordinate on the map
88     * @author	Lars Michelsen <lm@larsmichelsen.com>
89     */
90    public function getZ() {
91        return $this->z;
92    }
93
94    /**
95     * Get method for type of the object
96     *
97     * @return	String		Type of the object
98     * @author	Lars Michelsen <lm@larsmichelsen.com>
99     */
100    public function getType() {
101        return $this->type;
102    }
103
104    /**
105     * PUBLIC getObjectId()
106     *
107     * Get method for the object id
108     *
109     * @return	Integer		Object ID
110     * @author	Lars Michelsen <lm@larsmichelsen.com>
111     */
112    public function getObjectId() {
113        return $this->object_id;
114    }
115
116    /**
117     * PUBLIC setObjectId()
118     *
119     * Set method for the object id
120     *
121     * @param   Integer    Object id to set for the object
122     * @author  Lars Michelsen <lm@larsmichelsen.com>
123     */
124    public function setObjectId($id) {
125        $this->object_id = $id;
126    }
127
128    /**
129     * Get method for the name of the object
130     *
131     * @return	String		Name of the object
132     * @author	Lars Michelsen <lm@larsmichelsen.com>
133     */
134    public function getName() {
135        if($this->type == 'dyngroup' || $this->type == 'aggr') {
136            return $this->name;
137        } elseif ($this->type == 'service') {
138            return $this->host_name;
139        } else {
140            return $this->{$this->type.'_name'};
141        }
142    }
143
144    // Returns the display_name of an object, if available, otherwise
145    // the alias of an object, if available, otherwise the name
146    public function getDisplayName() {
147        if (isset($this->state[DISPLAY_NAME]) && $this->state[DISPLAY_NAME] != '')
148            return $this->state[DISPLAY_NAME];
149        elseif (isset($this->state[ALIAS]))
150            return $this->state[ALIAS];
151        else
152            return $this->getName();
153    }
154
155    /**
156     * Get method for the hover template of the object
157     *
158     * @return	String		Hover template of the object
159     * @author	Lars Michelsen <lm@larsmichelsen.com>
160     */
161    public function getHoverTemplate() {
162        return $this->hover_template;
163    }
164
165    /**
166     * Set method for the object coords
167     *
168     * @return	Array		Array of the objects coords
169     * @author	Lars Michelsen <lm@larsmichelsen.com>
170     */
171    public function setMapCoords($arrCoords) {
172        $this->setConfiguration($arrCoords);
173    }
174
175    /**
176     * PUBLIC setConfiguration()
177     *
178     * Sets options of the object
179     *
180     * @author	Lars Michelsen <lm@larsmichelsen.com>
181     */
182    public function setConfiguration($obj) {
183        foreach($obj AS $key => $val) {
184            $this->{$key} = $val;
185        }
186    }
187
188    /**
189     * PUBLIC setObjectInformation()
190     *
191     * Sets extended information of the object
192     *
193     * @author	Lars Michelsen <lm@larsmichelsen.com>
194     */
195    public function setObjectInformation($obj) {
196        foreach($obj AS $key => $val) {
197            $this->{$key} = $val;
198        }
199    }
200
201    /**
202     * PUBLIC getObjectInformation()
203     *
204     * Gets all necessary information of the object as array
205     *
206     * @return	Array		Object configuration
207     * @author 	Lars Michelsen <lm@larsmichelsen.com>
208     */
209    public function getObjectInformation($bFetchChilds = true) {
210        global $CORE;
211        $arr = Array();
212
213        // When the childs don't need to be fetched this object is a child
214        // itselfs. So much less information are needed. Progress them here
215        // If someone wants more information in hover menu children, this is
216        // the place to change.
217        if(!$bFetchChilds)
218            return $this->fetchObjectAsChild();
219
220        // Need to remove some options which are not relevant
221        // FIXME: Would be much better to name the needed vars explicit
222        if(self::$arrDenyKeys == null)
223            self::$arrDenyKeys = Array(
224                'MAPCFG' => '', 'MAP'  => '',
225                'conf' => '', 'services' => '', 'fetchedChildObjects' => '', 'childObjects' => '',
226                'parentObjects' => '', 'members' => '', 'objects' => '', 'linkedMaps' => '',
227                'isSummaryObject' => '', 'isView' => '', 'dateFormat' => '', 'arrDenyKeys' => '',
228                'aStateCounts' => '',	'iconDetails' => '', 'problem_msg' => '', 'isLoopingBacklink' => ''
229            );
230
231        foreach($this AS $key => $val)
232            if(!isset(self::$arrDenyKeys[$key]) && $val !== null)
233                $arr[$key] = $val;
234
235        if($this instanceof NagVisStatefulObject) {
236            $num_members = $this->getNumMembers();
237            if($num_members !== null)
238                $arr['num_members'] = $num_members;
239        }
240
241        // I want only "name" in js
242        if(!isset($CORE->statelessObjectTypes[$this->type])) {
243            $arr['name'] = $this->getName();
244
245            if($this->type == 'service') {
246                unset($arr['host_name']);
247            } else {
248                unset($arr[$this->type.'_name']);
249            }
250
251            if ($this->type == 'host' || $this->type == 'service') {
252                $obj_attrs = array(
253                    'alias'         => ALIAS,
254                    'display_name'  => DISPLAY_NAME,
255                    'address'       => ADDRESS,
256                    'notes'         => NOTES,
257                    'check_command' => CHECK_COMMAND,
258                );
259                foreach ($obj_attrs AS $attr => $state_key) {
260                    if (isset($this->state[$state_key]) && $this->state[$state_key] != '')
261                        $arr[$attr] = $this->state[$state_key];
262                    else
263                        $arr[$attr] = '';
264                }
265            } elseif ($this->type == 'map'
266                      || $this->type == 'servicegroup'
267                      || $this->type == 'hostgroup'
268                      || $this->type == 'aggregation') {
269                if (isset($this->state[ALIAS]))
270                    $arr['alias'] = $this->state[ALIAS];
271                else
272                    $arr['alias'] = '';
273            }
274
275            // Add the custom htmlcgi path for the object
276            $i = 0;
277            foreach($this->backend_id as $backend_id) {
278                if($i == 0) {
279                    $arr['htmlcgi']  = cfg('backend_'.$backend_id, 'htmlcgi');
280                    $arr['custom_1'] = cfg('backend_'.$backend_id, 'custom_1');
281                    $arr['custom_2'] = cfg('backend_'.$backend_id, 'custom_2');
282                    $arr['custom_3'] = cfg('backend_'.$backend_id, 'custom_3');
283                } else {
284                    $arr['htmlcgi_'.$i]  = cfg('backend_'.$backend_id, 'htmlcgi');
285                    $arr['custom_1_'.$i] = cfg('backend_'.$backend_id, 'custom_1');
286                    $arr['custom_2_'.$i] = cfg('backend_'.$backend_id, 'custom_2');
287                    $arr['custom_3_'.$i] = cfg('backend_'.$backend_id, 'custom_3');
288                }
289                $i++;
290            }
291
292            // Little hack: Overwrite the options with correct state information
293            $arr = array_merge($arr, $this->getObjectStateInformations(false));
294        }
295
296        // If there are some members fetch the information for them
297        if(isset($arr['num_members']) && $arr['num_members'] > 0) {
298            $members = Array();
299            foreach($this->getSortedObjectMembers() AS $OBJ) {
300                $members[] = $OBJ->fetchObjectAsChild();
301            }
302            $arr['members'] = $members;
303        }
304
305        return $arr;
306    }
307
308    /**
309     * PUBLIC getSortedObjectMembers()
310     *
311     * Gets an array of member objects
312     *
313     * @return	Array		Member object information
314     * @author 	Lars Michelsen <lm@larsmichelsen.com>
315     */
316    public function getSortedObjectMembers() {
317        $arr = Array();
318
319        $aTmpMembers = $this->getStateRelevantMembers();
320
321        // Set the sort order
322        self::$sSortOrder = $this->hover_childs_order;
323
324        // Sort the array of child objects by the sort option
325        switch($this->hover_childs_sort) {
326            case 's':
327                // Order by State
328                usort($aTmpMembers, Array("NagVisObject", "sortObjectsByState"));
329            break;
330            case 'k':
331                // Keep original order (as provided by backend)
332            break;
333            case 'a':
334            default:
335                // Order alhpabetical
336                usort($aTmpMembers, Array("NagVisObject", "sortObjectsAlphabetical"));
337            break;
338        }
339
340        // Count only once, not in loop header
341        $iNumObjects = count($aTmpMembers);
342
343        // Loop all child object until all looped or the child limit is reached
344        for($i = 0; $this->belowHoverChildsLimit($i) && $i < $iNumObjects; $i++) {
345            $arr[] = $aTmpMembers[$i];
346        }
347
348        return $arr;
349    }
350
351    /**
352     * PUBLIC getObjectConfiguration()
353     *
354     * Gets the configuration of the object
355     *
356     * @return	Array		Object configuration
357     * @author 	Lars Michelsen <lm@larsmichelsen.com>
358     */
359    public function getObjectConfiguration($abstract = true) {
360        // Some options have to be removed which are only for this object
361        $arr = $this->conf;
362        unset($arr['id']);
363        unset($arr['object_id']);
364        unset($arr['type']);
365
366        // Only remove these options when the configuration should be
367        // completely independent from this object
368        if($abstract == true) {
369            unset($arr['host_name']);
370            unset($arr[$this->type.'_name']);
371            unset($arr['service_description']);
372        }
373
374        return $arr;
375    }
376
377    /**
378     * PUBLIC parseJson()
379     *
380     * Parses the object in json format
381     *
382     * @return	String  JSON code of the object
383     * @author	Lars Michelsen <lm@larsmichelsen.com>
384     */
385    public function parseJson() {
386        return $this->getObjectInformation();
387    }
388
389    /**
390     * PUBLIC parseMapCfg()
391     *
392     * Parses the object in map configuration format
393     *
394     * @param   Array   Array of global map options
395     * @return	String  This object in map config format
396     * @author	Lars Michelsen <lm@larsmichelsen.com>
397     */
398    public function parseMapCfg($globalOpts = Array()) {
399        $ret = 'define '.$this->type." {\n";
400        if($this->type === 'host')
401            $ret .= '  host_name='.$this->host_name."\n";
402        $ret .= '  object_id='.$this->object_id."\n";
403        foreach($this->getObjectConfiguration(false) AS $key => $val) {
404            // Only set options which are different to global option
405            if((!isset($globalOpts[$key]) || $globalOpts[$key] != $val) && $val != '') {
406                $ret .= '  '.$key.'='.$val."\n";
407            }
408        }
409        $ret .= "}\n\n";
410
411        return $ret;
412    }
413
414    /**
415     * PUBLIC getUrl()
416     * Returns the url for the object link
417     */
418    public function getUrl() {
419        if(isset($this->url)) {
420            return $this->url;
421        } else {
422            return '';
423        }
424    }
425
426    # End public methods
427    # #########################################################################
428
429    /**
430     * PROTECTED getUrlTarget()
431     *
432     * Returns the target frame for the object link
433     *
434     * @return	String	Target
435     * @author 	Lars Michelsen <lm@larsmichelsen.com>
436     */
437    protected function getUrlTarget() {
438        return $this->url_target;
439    }
440
441    /**
442     * PRIVATE STATIC sortObjectsAlphabetical()
443     *
444     * Sorts both objects alphabetically by name
445     *
446     * @param	OBJ		First object to sort
447     * @param	OBJ		Second object to sort
448     * @author 	Lars Michelsen <lm@larsmichelsen.com>
449     */
450    private static function sortObjectsAlphabetical($OBJ1, $OBJ2) {
451        if($OBJ1->type == 'service') {
452            $name1 = strtolower($OBJ1->getName().$OBJ1->getServiceDescription());
453        } else {
454            $name1 = strtolower($OBJ1->getName());
455        }
456
457        if($OBJ2->type == 'service') {
458            $name2 = strtolower($OBJ2->getName().$OBJ2->getServiceDescription());
459        } else {
460            $name2 = strtolower($OBJ2->getName());
461        }
462
463        if ($name1 == $name2) {
464            return 0;
465        } elseif($name1 > $name2) {
466            // Sort depending on configured direction
467            if(self::$sSortOrder === 'asc') {
468                return +1;
469            } else {
470                return -1;
471            }
472        } else {
473            // Sort depending on configured direction
474            if(self::$sSortOrder === 'asc') {
475                return -1;
476            } else {
477                return +1;
478            }
479        }
480    }
481
482    /**
483     * PRIVATE STATIC sortObjectsByState()
484     *
485     * Sorts both by state of the object
486     *
487     * @param	OBJ		First object to sort
488     * @param	OBJ		Second object to sort
489     * @author 	Lars Michelsen <lm@larsmichelsen.com>
490     */
491    private static function sortObjectsByState($OBJ1, $OBJ2) {
492        $state1 = $OBJ1->sum[STATE];
493        $subState1 = $OBJ1->getSubState(SUMMARY_STATE);
494
495        $state2 = $OBJ2->sum[STATE];
496        $subState2 = $OBJ2->getSubState(SUMMARY_STATE);
497
498        return NagVisObject::sortStatesByStateValues($state1, $subState1, $state2, $subState2, self::$sSortOrder);
499    }
500
501    /**
502     * Helper to sort states independent of objects
503     */
504    public static function sortStatesByStateValues($state1, $subState1, $state2, $subState2, $sortOrder) {
505        global $_MAINCFG;
506
507        // Quit when nothing to compare
508        if($state1 === null || $state2 === null) {
509            return 0;
510        }
511
512        $stateWeight = $_MAINCFG->getStateWeight();
513
514        // Handle normal/ack/downtime states
515        if($stateWeight[$state1][$subState1] == $stateWeight[$state2][$subState2]) {
516            return 0;
517        } elseif($stateWeight[$state1][$subState1] < $stateWeight[$state2][$subState2]) {
518            // Sort depending on configured direction
519            if($sortOrder === 'asc') {
520                return +1;
521            } else {
522                return -1;
523            }
524        } else {
525            // Sort depending on configured direction
526            if($sortOrder === 'asc') {
527                return -1;
528            } else {
529                return +1;
530            }
531        }
532    }
533}
534?>
535