2019-03-07 18:57:48 +01:00
< ? php
/**
* Class to manage networkmaps in Pandora FMS
*
* @ category Class
* @ package Pandora FMS
* @ subpackage NetworkMap manager
* @ version 1.0 . 0
* @ license See below
*
* ______ ___ _______ _______ ________
* | __ \ .-----.--.--.--| |.-----.----.-----. | ___ | | | __ |
* | __ /| _ | | _ || _ | _ | _ | | ___ | | __ |
* | ___ | | ___ . _ | __ | __ | _____ || _____ | __ | | ___ . _ | | ___ | | __ | _ | __ | _______ |
*
* ============================================================================
2020-11-27 13:52:35 +01:00
* Copyright ( c ) 2005 - 2021 Artica Soluciones Tecnologicas
2019-03-07 18:57:48 +01:00
* Please see http :// pandorafms . org for full contribution list
* 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 .
* ============================================================================
*/
// Begin.
global $config ;
2019-03-11 20:10:08 +01:00
require_once $config [ 'homedir' ] . '/include/functions_networkmap.php' ;
2019-03-15 20:44:57 +01:00
enterprise_include_once ( 'include/functions_discovery.php' );
// Avoid node overlapping.
2019-03-29 20:31:55 +01:00
define ( 'GRAPHVIZ_CONVERSION_FACTOR' , 30 );
define ( 'MAP_X_CORRECTION' , 0 );
define ( 'MAP_Y_CORRECTION' , 0 );
2019-03-18 18:11:54 +01:00
2019-03-11 20:10:08 +01:00
2019-03-07 18:57:48 +01:00
/**
2019-03-17 01:39:56 +01:00
* Manage networkmaps in Pandora FMS .
*
* General steps :
* Generate a list of nodes .
* For each node , calculate relationship and add several 'module' nodes
* representing interface nodes .
* Once the base arrays are formed ( nodes and relations ), this class
* calls graphviz to calculate X , Y positions for given nodes .
* Translates node - relationship - positioning data into processed
* 'nodes_and_relations' .
* When printMap is called . Several information is sent to browser :
* - Base DOM items where place target map .
* - JS controllers .
* - Data translated to JSON format .
* - Interface layer .
2019-03-22 03:56:31 +01:00
*
* Basic parameters for NetworkMap class constructor :
*
* nodes => is really 'rawNodes' here you put an array like follows :
* nodes => [
* 'some_id' => [
* 'type' => NODE_GENERIC / NODE_PANDORA / NODE_MODULE / NODE_AGENT ,
* behaviour and fields to be used are different depending
* on the type .
* 'id_agente' => 'some_id' ,
* 'status' => 'agent status' ,
* 'id_parent' => ' target parent to match in map , its no need to use the
* real parent but must match some_id '
* 'id_node' => incremental id ( 0 , 1 , 2 , 3. .. ),
* 'image' => relative path to image to use ,
* 'label' => label to use ( in NODE_GENERIC )
* ]
* ]
*
* Tooltipster support : Keep in mind , using tooltipster behaviour
* of map changes .
*
* Sample usage :
*
* < code >
*
* $map_manager = new NetworkMap (
* [
* 'nodes' => vmware_get_nodes ( $show_vms , $show_ds , $show_esx ),
* 'pure' => 1 ,
* 'use_tooltipster' => 1 ,
* 'tooltip_params' => [
* 'page' => 'operation/agentes/ver_agente' ,
* 'get_agent_json' => 1 ,
* ],
* ]
* );
*
* $map_manager -> printMap ();
*
* </ code >
2019-03-07 18:57:48 +01:00
*/
class NetworkMap
{
/**
2019-03-17 01:39:56 +01:00
* Target map Id , from tmap . If the maps is being simulated
* then the idMap value will be uniqid .
2019-03-07 18:57:48 +01:00
*
* @ var integer
*/
public $idMap ;
2019-03-11 15:09:31 +01:00
/**
2019-03-17 01:39:56 +01:00
* Content of tmap . Map definition . If the map is being simulated
* then defaults to constructor received parameters .
2019-03-11 15:09:31 +01:00
*
* @ var array
*/
public $map ;
/**
* Data origin , network .
*
* @ var string
*/
public $network ;
/**
* Data origin , group id .
*
* @ var integer
*/
public $idGroup ;
/**
* Data origin , Discovery task .
*
* @ var integer
*/
public $idTask ;
2019-03-07 18:57:48 +01:00
/**
2019-03-17 01:39:56 +01:00
* Graph definition . Previously was 'nodes_and_relationships'
* Is the data format before be translated to JS variables .
2019-03-07 18:57:48 +01:00
*
* @ var array
*/
public $graph ;
2019-03-11 20:10:08 +01:00
/**
* Dot string with graph definition .
2019-03-17 01:39:56 +01:00
* Its contents will be send to graphviz to calculate node positions .
2019-03-11 20:10:08 +01:00
*
* @ var string
*/
public $dotGraph ;
2019-03-07 18:57:48 +01:00
/**
2019-03-21 16:16:53 +01:00
* Node list processed by NetworkMap class .
*
* @ var array
*/
public $nodes ;
/**
* Node list RAW .
2019-03-17 01:39:56 +01:00
* A simple list of nodes , could content information of agents , modules ...
* Is the 'raw' information .
2019-03-07 18:57:48 +01:00
*
* @ var array
*/
2019-03-21 16:16:53 +01:00
public $rawNodes ;
2019-03-07 18:57:48 +01:00
2019-03-15 20:44:57 +01:00
/**
* Useful to translate id_node to id_agent or id_module .
2019-03-17 01:39:56 +01:00
* Maps built nodes to original node information ( agents , modules ) .
2019-03-15 20:44:57 +01:00
*
* @ var array
*/
public $nodeMapping ;
2019-03-07 18:57:48 +01:00
/**
* Relationship map .
2019-03-17 01:39:56 +01:00
* Each element contents :
* id_parent
* id_child
* parent_type
* child_type
* id_parent_source_data ( from $this -> nodes )
* id_child_source_data ( from $this -> nodes )
2019-03-07 18:57:48 +01:00
*
* @ var array
*/
public $relations ;
2019-03-29 20:52:51 +01:00
/**
* Private nodes converted to JS .
*
* @ var array
*/
private $nodesJS ;
/**
* Private relations converted to JS .
*
* @ var array
*/
private $relationsJS ;
2019-03-07 18:57:48 +01:00
/**
2019-03-22 03:56:31 +01:00
* Include a Pandora ( or vendor ) node or not .
2019-03-07 18:57:48 +01:00
*
* @ var integer
*/
2019-03-22 03:56:31 +01:00
public $noPandoraNode ;
/**
* Use tooltipster interface instead of standard .
*
* @ var boolean
*/
public $useTooltipster ;
/**
* Options used in AJAX call while using tooltipster .
*
* @ var array
*/
public $tooltipParams ;
2020-02-06 14:32:43 +01:00
/**
* Defines if map is widget or not for JS
*
* @ var boolean ;
*/
public $widget ;
2019-03-27 11:47:09 +01:00
/**
* Shows the map using 100 % of height and width if is a widget .
*
* @ var boolean
*/
2019-03-27 18:31:02 +01:00
public $fullSize ;
2019-03-27 11:47:09 +01:00
2019-03-22 03:56:31 +01:00
/**
* Defines a custom method to parse Graphviz output and generate Graph .
* Function pointer .
*
* @ var string
*/
public $customParser ;
/**
* Defines arguments to be passed to $customParser .
* If is not defined , default arguments will be used .
*
* @ var array
*/
public $customParserArgs ;
/**
* If using a custom parser , fallback to default parser while
* found exceptions .
*
* @ var boolean
*/
public $fallbackDefaultParser ;
2019-03-07 18:57:48 +01:00
/**
2019-03-17 01:39:56 +01:00
* Array of map options . Because how is built , the structure matches
* with tmap definition , where map_filter is the json - extracted data .
* Duplicate options appears since tmap stores information in different
* ways ( simplifies process ) .
* If an idMap is defined , map is loaded into this structure and used along
* the class .
* generation_method
* simple
* font_size
* nooverlap
* z_dash
* ranksep
* center
* regen
* pure
* show_snmp_modules
* cut_names
* relative
* text_filter
* dont_show_subgroups
* strict_user
* size_canvas
* old_mode
* map_filter ( array )
* dont_show_subgroups
* node_radius
* x_offs
* y_offs
* z_dash
* node_sep
* rank_sep
* mindist
* kval
2019-03-07 18:57:48 +01:00
*
* @ var array
*/
public $mapOptions ;
2019-03-17 01:39:56 +01:00
/**
* Filter ( command ) to use to calculate node positions .
*
* @ var string
*/
private $filter ;
2019-03-26 15:27:45 +01:00
/**
* Do not show the popup window .
*
* @ var integer
*/
private $noPopUp ;
2019-03-07 18:57:48 +01:00
/**
* Base constructor .
*
2019-03-11 15:09:31 +01:00
* @ param mixed $options Could define in array as :
* id_map => target discovery task id .
* id_group => target group .
* network => target CIDR .
* graph => target graph ( already built ) .
2019-03-07 18:57:48 +01:00
* nodes => target agents or nodes .
* relations => target array of relationships .
2019-03-11 15:09:31 +01:00
* mode => simple ( 0 ) or advanced ( 1 ) .
* map_options => Map options .
2019-03-07 18:57:48 +01:00
*
* @ return object New networkmap manager .
*/
2019-03-11 15:09:31 +01:00
public function __construct ( $options = false )
2019-03-07 18:57:48 +01:00
{
2019-03-21 16:16:53 +01:00
global $config ;
2019-03-11 20:10:08 +01:00
// Default mapOptions values.
2019-03-12 16:22:28 +01:00
// Defines the command to generate positions.
$this -> mapOptions [ 'generation_method' ] = LAYOUT_SPRING1 ;
2019-03-29 20:31:55 +01:00
// Use fixed positions defined (X,Y) per node.
$this -> mapOptions [ 'fixed_positions' ] = 0 ;
2019-03-21 16:16:53 +01:00
$this -> mapOptions [ 'width' ] = $config [ 'networkmap_max_width' ];
$this -> mapOptions [ 'height' ] = $config [ 'networkmap_max_width' ];
2019-03-11 20:10:08 +01:00
$this -> mapOptions [ 'simple' ] = 0 ;
2019-03-27 12:42:54 +01:00
$this -> mapOptions [ 'font_size' ] = 20 ;
2019-03-11 20:10:08 +01:00
$this -> mapOptions [ 'nooverlap' ] = 1 ;
2019-03-12 16:22:28 +01:00
$this -> mapOptions [ 'z_dash' ] = 0.5 ;
2019-03-11 20:10:08 +01:00
$this -> mapOptions [ 'center' ] = 0 ;
$this -> mapOptions [ 'regen' ] = 0 ;
2019-03-12 18:32:55 +01:00
$this -> mapOptions [ 'pure' ] = 0 ;
2019-03-11 20:10:08 +01:00
$this -> mapOptions [ 'show_snmp_modules' ] = false ;
$this -> mapOptions [ 'cut_names' ] = false ;
$this -> mapOptions [ 'relative' ] = true ;
$this -> mapOptions [ 'text_filter' ] = '' ;
$this -> mapOptions [ 'dont_show_subgroups' ] = false ;
$this -> mapOptions [ 'strict_user' ] = false ;
2019-03-19 20:43:08 +01:00
$this -> mapOptions [ 'size_canvas' ] = 0 ;
2019-03-11 20:10:08 +01:00
$this -> mapOptions [ 'old_mode' ] = false ;
$this -> mapOptions [ 'map_filter' ] = [
2019-03-12 10:29:19 +01:00
'dont_show_subgroups' => 0 ,
'node_radius' => 40 ,
'x_offs' => 0 ,
'y_offs' => 0 ,
'z_dash' => 0.5 ,
2019-03-21 16:16:53 +01:00
'node_sep' => 5 ,
2019-03-17 01:39:56 +01:00
'rank_sep' => 5 ,
2019-03-12 10:29:19 +01:00
'mindist' => 1 ,
'kval' => 0.1 ,
2019-03-11 20:10:08 +01:00
];
2019-03-07 18:57:48 +01:00
if ( is_array ( $options )) {
2019-03-12 12:05:54 +01:00
// Previously nodes_and_relations.
2019-03-07 18:57:48 +01:00
if ( isset ( $options [ 'graph' ])) {
$this -> graph = $options [ 'graph' ];
}
2019-03-12 12:05:54 +01:00
// String dotmap.
if ( isset ( $options [ 'dot_graph' ])) {
$this -> dotGraph = $options [ 'dot_graph' ];
}
// Array of nodes, agents, virtual, etc.
2019-03-07 18:57:48 +01:00
if ( isset ( $options [ 'nodes' ])) {
2019-03-21 16:16:53 +01:00
$this -> rawNodes = $options [ 'nodes' ];
2019-03-07 18:57:48 +01:00
}
2019-03-12 12:05:54 +01:00
// Array of relations.
2019-03-07 18:57:48 +01:00
if ( isset ( $options [ 'relations' ])) {
$this -> relations = $options [ 'relations' ];
}
2019-03-12 12:05:54 +01:00
// User interface type. Simple or advanced.
2019-03-07 18:57:48 +01:00
if ( isset ( $options [ 'mode' ])) {
$this -> mode = $options [ 'mode' ];
}
2019-03-12 18:32:55 +01:00
// Show interface elements or dashboard style.
if ( isset ( $options [ 'pure' ])) {
$this -> mapOptions [ 'pure' ] = $options [ 'pure' ];
}
2019-03-22 03:56:31 +01:00
if ( isset ( $options [ 'no_pandora_node' ])) {
$this -> noPandoraNode = $options [ 'no_pandora_node' ];
}
2019-03-26 15:27:45 +01:00
if ( isset ( $options [ 'no_popup' ])) {
$this -> noPopUp = $options [ 'no_popup' ];
}
2019-03-27 11:47:09 +01:00
// Initialize as widget?
if ( isset ( $options [ 'widget' ])) {
2019-03-27 18:31:02 +01:00
$this -> fullSize = ( bool ) $options [ 'widget' ];
2020-02-06 14:32:43 +01:00
$this -> widget = true ;
2019-03-27 18:31:02 +01:00
} else {
$this -> fullSize = true ;
2020-02-06 14:32:43 +01:00
$this -> widget = false ;
2019-03-27 11:47:09 +01:00
}
2019-03-22 03:56:31 +01:00
// Use a custom parser.
if ( isset ( $options [ 'custom_parser' ])) {
$this -> customParser = $options [ 'custom_parser' ];
}
// Custom parser arguments.
if ( isset ( $options [ 'custom_parser_args' ])) {
if ( is_array ( $options [ 'custom_parser_args' ])) {
foreach ( $options [ 'custom_parser_args' ] as $k ) {
$this -> customParserArgs [] = $k ;
}
} else {
$this -> customParserArgs = $options [ 'custom_parser_args' ];
}
}
// Fallback to default parser.
if ( isset ( $options [ 'fallback_to_default_parser' ])) {
$this -> fallbackDefaultParser = $options [ 'fallback_to_default_parser' ];
}
if ( isset ( $options [ 'use_tooltipster' ])) {
$this -> useTooltipster = $options [ 'use_tooltipster' ];
}
if ( is_array ( $options [ 'tooltip_params' ])) {
foreach ( $options [ 'tooltip_params' ] as $k => $v ) {
$this -> tooltipParams [ $k ] = $v ;
}
}
2019-03-12 12:05:54 +01:00
// Map options, check default values above.
// This is only used while generating new maps using
// (generateDotGraph).
2019-03-19 20:43:08 +01:00
if ( isset ( $options [ 'map_options' ])
&& is_array ( $options [ 'map_options' ])
) {
2019-03-11 20:10:08 +01:00
foreach ( $options [ 'map_options' ] as $k => $v ) {
2019-03-22 14:57:29 +01:00
if ( $k == 'map_filter' && is_array ( $v )) {
foreach ( $v as $kc => $vc ) {
$this -> mapOptions [ 'map_filter' ][ $kc ] = $vc ;
}
} else {
$this -> mapOptions [ $k ] = $v ;
}
2019-03-11 20:10:08 +01:00
}
2019-03-07 18:57:48 +01:00
}
2019-03-11 15:09:31 +01:00
2019-03-12 12:05:54 +01:00
// Load from tmap.
2019-03-11 15:09:31 +01:00
if ( $options [ 'id_map' ]) {
$this -> idMap = $options [ 'id_map' ];
// Update nodes and relations.
$this -> loadMap ();
if ( empty ( $this -> nodes )
2019-03-14 18:51:48 +01:00
&& empty ( $this -> relations )
2019-03-11 15:09:31 +01:00
) {
$this -> createMap ();
}
} else {
2019-03-12 12:05:54 +01:00
// Generate from group, task or network.
2019-03-11 15:09:31 +01:00
if ( $options [ 'id_group' ]) {
$this -> idGroup = $options [ 'id_group' ];
}
if ( $options [ 'id_task' ]) {
$this -> idTask = $options [ 'id_task' ];
}
if ( $options [ 'network' ]) {
$this -> network = $options [ 'network' ];
}
$this -> createMap ();
}
2019-03-07 18:57:48 +01:00
}
return $this ;
}
2019-03-11 15:09:31 +01:00
/**
* Creates a new map based on a target .
*
* Target is specified from constructor arguments .
* options :
* - id_task => create a map from task .
* - id_group => create a map from group .
* - network => create a map from network .
*
* @ return void
*/
public function createMap ()
{
2020-05-21 19:28:24 +02:00
global $config ;
2019-03-12 12:05:54 +01:00
// If exists, load from DB.
2019-03-11 15:09:31 +01:00
if ( $this -> idMap ) {
$this -> loadMap ();
return ;
}
2019-03-12 12:05:54 +01:00
// Simulated map.
$this -> idMap = uniqid ();
// No tmap definition. Paint data.
if ( $this -> idTask ) {
$recon_task = db_get_row_filter (
'trecon_task' ,
2019-03-12 16:22:28 +01:00
[ 'id_rt' => $this -> idTask ]
2019-03-11 15:09:31 +01:00
);
2019-03-12 12:05:54 +01:00
$this -> network = $recon_task [ 'subnet' ];
2019-03-11 15:09:31 +01:00
}
2019-03-11 20:10:08 +01:00
2019-03-12 12:05:54 +01:00
// Simulate map entry.
$this -> map = [
'id' => $this -> idMap ,
'__simulated' => 1 ,
'background' => '' ,
'background_options' => 0 ,
'source_period' => 60 ,
'filter' => $this -> mapOptions [ 'map_filter' ],
2019-03-21 16:16:53 +01:00
'width' => $config [ 'networkmap_max_width' ],
'height' => $config [ 'networkmap_max_width' ],
2019-03-12 16:22:28 +01:00
'center_x' => 0 ,
'center_y' => 0 ,
2019-03-12 12:05:54 +01:00
];
2019-03-17 01:39:56 +01:00
if ( isset ( $this -> mapOptions [ 'generation_method' ]) === false ) {
$this -> mapOptions [ 'generation_method' ] = LAYOUT_SPRING1 ;
}
// Load filter.
$this -> loadFilter ();
2019-03-12 16:22:28 +01:00
// Will be stored in $this->graph.
$this -> generateNetworkMap ();
2019-03-12 12:05:54 +01:00
2019-03-11 15:09:31 +01:00
}
2019-03-17 01:39:56 +01:00
/**
* Update filter and layout based on generation_method selected .
*
* @ return boolean True or false .
*/
private function loadFilter ()
{
if ( is_array ( $this -> mapOptions ) === false ) {
return false ;
}
switch ( $this -> mapOptions [ 'generation_method' ]) {
case LAYOUT_CIRCULAR :
$this -> filter = 'circo' ;
$this -> mapOptions [ 'layout' ] = 'circular' ;
break ;
case LAYOUT_FLAT :
$this -> filter = 'dot' ;
$this -> mapOptions [ 'layout' ] = 'flat' ;
break ;
case LAYOUT_RADIAL :
$this -> filter = 'twopi' ;
$this -> mapOptions [ 'layout' ] = 'radial' ;
break ;
case LAYOUT_SPRING1 :
default :
$this -> filter = 'neato' ;
$this -> mapOptions [ 'layout' ] = 'spring1' ;
break ;
case LAYOUT_SPRING2 :
$this -> filter = 'fdp' ;
$this -> mapOptions [ 'layout' ] = 'spring2' ;
break ;
}
return true ;
}
2019-03-11 15:09:31 +01:00
/**
* Loads a map from a target map ID .
*
* @ return void .
*/
public function loadMap ()
{
2019-03-12 16:22:28 +01:00
if ( $this -> map ) {
// Already loaded.
return ;
}
2019-03-11 15:09:31 +01:00
if ( $this -> idMap ) {
$this -> map = db_get_row ( 'tmap' , 'id' , $this -> idMap );
2019-03-12 16:22:28 +01:00
$this -> mapOptions [ 'map_filter' ] = json_decode (
$this -> map [ 'filter' ],
true
);
foreach ( $this -> map as $k => $v ) {
$this -> mapOptions [ $k ] = $v ;
}
2019-03-17 01:39:56 +01:00
// Load filter.
$this -> loadFilter ();
2019-03-12 16:22:28 +01:00
// Retrieve data origin.
$this -> network = null ;
$this -> idTask = null ;
$this -> idGroup = $this -> map [ 'id_group' ];
switch ( $this -> map [ 'source' ]) {
case SOURCE_TASK :
$this -> idTask = $this -> map [ 'source_data' ];
break ;
case SOURCE_NETWORK :
$this -> network = $this -> map [ 'source_data' ];
break ;
2019-03-26 16:46:32 +01:00
case SOURCE_GROUP :
// Already load.
2019-03-12 16:22:28 +01:00
default :
// Ignore.
break ;
}
if ( $this -> idTask ) {
$recon_task = db_get_row_filter (
'trecon_task' ,
2019-03-15 20:44:57 +01:00
[ 'id_rt' => $this -> idTask ]
2019-03-12 16:22:28 +01:00
);
$this -> network = $recon_task [ 'subnet' ];
}
2019-03-11 15:09:31 +01:00
// Retrieve or update nodes and relations.
$this -> getNodes ();
$this -> getRelations ();
2019-03-12 16:22:28 +01:00
// Nodes and relations will be stored in $this->graph.
$this -> loadGraph ();
2019-03-11 15:09:31 +01:00
}
}
2019-03-15 20:44:57 +01:00
/**
* Retrieves node information using id_node as mapping instead element id .
*
* @ param integer $id_node Target node .
* @ param string $field Field to retrieve , if null , all are return .
*
2019-03-17 01:39:56 +01:00
* @ return mixed Array ( node data ) or null if error .
2019-03-15 20:44:57 +01:00
*/
public function getNodeData ( int $id_node , $field = null )
{
if ( is_array ( $this -> nodes ) === false
|| is_array ( $this -> nodeMapping ) === false
) {
2019-03-17 01:39:56 +01:00
return null ;
2019-03-15 20:44:57 +01:00
}
if ( is_array ( $this -> nodes [ $this -> nodeMapping [ $id_node ]]) === true ) {
if ( isset ( $field ) === false ) {
return $this -> nodes [ $this -> nodeMapping [ $id_node ]];
} else {
return $this -> nodes [ $this -> nodeMapping [ $id_node ]][ $field ];
}
} else {
2019-03-17 01:39:56 +01:00
return null ;
2019-03-15 20:44:57 +01:00
}
}
2019-03-20 13:10:20 +01:00
/**
* Set nodes .
*
* @ param array $nodes Nodes definition .
*
* @ return void
*/
public function setNodes ( $nodes )
{
$this -> nodes = $nodes ;
}
2019-03-11 15:09:31 +01:00
/**
* Return nodes of current map .
*
* @ return array Nodes .
*/
public function getNodes ()
{
if ( $this -> nodes ) {
return $this -> nodes ;
}
if ( $this -> idMap !== false ) {
2021-09-23 17:01:22 +02:00
$this -> nodes = get_nodes_from_db ( $this -> idMap );
2019-03-11 15:09:31 +01:00
}
return $this -> nodes ;
}
2019-03-20 13:10:20 +01:00
/**
* Set relations .
*
* @ param array $relations Relations definition .
*
* @ return void
*/
public function setRelations ( $relations )
{
$this -> relations = $relations ;
}
2019-03-12 16:22:28 +01:00
/**
* Return relations of current map .
*
* @ return array Relations .
*/
public function getRelations ()
{
if ( $this -> relations ) {
return $this -> relations ;
}
if ( $this -> idMap !== false ) {
2021-09-23 17:01:22 +02:00
$this -> relations = get_relations_from_db ( $this -> idMap );
2019-03-12 16:22:28 +01:00
}
return $this -> relations ;
}
2019-03-15 20:44:57 +01:00
/**
* Search for nodes in current map definition .
*
2019-03-17 01:39:56 +01:00
* @ return array Nodes detected , internal variable NOT updated .
2019-03-15 20:44:57 +01:00
*/
public function calculateNodes ()
{
2019-03-17 01:39:56 +01:00
global $config ;
2019-03-15 20:44:57 +01:00
// Calculate.
2019-03-17 01:39:56 +01:00
// Search.
2021-09-23 17:01:22 +02:00
if ( $this -> idTask ) {
2019-03-17 01:39:56 +01:00
// Network map, based on discovery task.
2021-09-23 17:01:22 +02:00
return get_discovery_agents ( $this -> idTask );
2019-03-17 01:39:56 +01:00
}
2019-03-15 20:44:57 +01:00
2019-03-17 01:39:56 +01:00
if ( $this -> network ) {
// Network map, based on direct network.
2019-03-22 19:16:45 +01:00
$nodes = networkmap_get_nodes_from_ip_mask (
2019-03-17 01:39:56 +01:00
$this -> network
);
} else if ( $this -> mapOptions [ 'map_filter' ][ 'empty_map' ]) {
// Empty map returns no data.
$nodes = [];
} else {
2019-03-26 17:00:20 +01:00
if ( $this -> mapOptions [ 'map_filter' ][ 'dont_show_subgroups' ] === 'true'
2019-03-26 16:46:32 +01:00
|| $this -> mapOptions [ 'map_filter' ][ 'dont_show_subgroups' ] == 1
) {
2019-03-22 18:27:12 +01:00
// Show only current selected group.
$filter [ 'id_grupo' ] = $this -> idGroup ;
} else {
// Show current group and children.
2020-10-21 11:38:57 +02:00
$childrens = groups_get_children ( $this -> idGroup , null , true );
2019-03-22 18:27:12 +01:00
if ( ! empty ( $childrens )) {
$childrens = array_keys ( $childrens );
$filter [ 'id_grupo' ] = $childrens ;
$filter [ 'id_grupo' ][] = $this -> idGroup ;
} else {
$filter [ 'id_grupo' ] = $this -> idGroup ;
}
}
2019-03-17 01:39:56 +01:00
// Group map.
$nodes = agents_get_agents (
2019-03-22 18:27:12 +01:00
$filter ,
2019-03-18 18:11:54 +01:00
[ '*' ],
2019-03-17 01:39:56 +01:00
'AR' ,
[
'field' => 'id_parent' ,
'order' => 'ASC' ,
]
);
2019-03-21 21:34:56 +01:00
2019-03-22 18:27:12 +01:00
if ( is_array ( $nodes )) {
// Remap ids.
$nodes = array_reduce (
$nodes ,
function ( $carry , $item ) {
$carry [ $item [ 'id_agente' ]] = $item ;
return $carry ;
}
);
} else {
$nodes = [];
}
2019-03-15 20:44:57 +01:00
}
2019-03-17 01:39:56 +01:00
return $nodes ;
2019-03-15 20:44:57 +01:00
}
/**
* Search for relations for a given node in current map definition .
2019-03-17 01:39:56 +01:00
* Use id_parent in custom node definition to create an edge between
* two nodes .
2019-03-15 20:44:57 +01:00
*
2019-03-17 01:39:56 +01:00
* Representation is to => from because from could be equal in multiple
* edges but no to ( 1 origin , multiple targets ) .
*
* @ param array $id_source Id for source data , agent , module or custom .
2019-03-15 20:44:57 +01:00
*
* @ return array Relations found for given node .
*/
public function calculateRelations (
$id_source
) {
// Calculate.
2019-03-17 01:39:56 +01:00
$node = $this -> nodes [ $id_source ];
2019-03-15 20:44:57 +01:00
if ( is_array ( $node ) === false ) {
return false ;
}
$relations = [];
2019-03-18 18:11:54 +01:00
$i = 0 ;
$from_type = NODE_AGENT ;
$to_type = NODE_AGENT ;
2019-03-17 01:39:56 +01:00
switch ( $node [ 'node_type' ]) {
case NODE_AGENT :
// Search for agent parent and module relationships.
$module_relations = modules_get_relations (
2019-03-18 18:11:54 +01:00
[ 'id_agent' => $node [ 'id_agente' ]]
2019-03-17 01:39:56 +01:00
);
2019-03-18 18:11:54 +01:00
2019-03-17 01:39:56 +01:00
if ( $module_relations !== false ) {
2019-03-18 18:11:54 +01:00
// Module relation exist.
foreach ( $module_relations as $mod_rel ) {
// Check if target referenced agent is defined in
// current map.
$agent_a = modules_get_agentmodule_agent (
$mod_rel [ 'module_a' ]
);
$module_a = $mod_rel [ 'module_a' ];
$agent_b = modules_get_agentmodule_agent (
$mod_rel [ 'module_b' ]
);
$module_b = $mod_rel [ 'module_b' ];
// Calculate target.
$module_to = $module_a ;
$agent_to = $agent_a ;
$module_from = $module_b ;
$agent_from = $agent_b ;
// Module relations does not have from and to,
// If current agent_a is current node, reverse relation.
if ( $agent_a == $node [ 'id_agente' ]) {
$module_to = $module_b ;
$agent_to = $agent_b ;
$module_from = $module_a ;
$agent_from = $agent_a ;
}
2019-03-17 01:39:56 +01:00
2019-03-18 18:11:54 +01:00
$target_node = $this -> nodes [ NODE_AGENT . '_' . $agent_to ];
2019-03-17 01:39:56 +01:00
2019-03-18 18:11:54 +01:00
if ( isset ( $target_node ) === false ) {
// Agent is not present in this map.
2019-03-17 01:39:56 +01:00
continue ;
}
2019-03-15 20:44:57 +01:00
2019-03-18 18:11:54 +01:00
$rel = [];
// Node reference (child).
$rel [ 'id_child' ] = $node [ 'id_node' ];
$rel [ 'child_type' ] = NODE_MODULE ;
$rel [ 'id_child_source_data' ] = $module_from ;
$rel [ 'id_child_agent' ] = $agent_from ;
// Node reference (parent).
$rel [ 'id_parent' ] = $target_node [ 'id_node' ];
$rel [ 'parent_type' ] = NODE_MODULE ;
$rel [ 'id_parent_source_data' ] = $module_to ;
$rel [ 'id_parent_agent' ] = $agent_to ;
// Store relation.
$relations [] = $rel ;
2019-03-17 01:39:56 +01:00
}
}
2019-03-15 20:44:57 +01:00
2019-03-17 01:39:56 +01:00
// Add also parent relationship.
$parent_id = NODE_AGENT . '_' . $node [ 'id_parent' ];
2019-03-22 13:16:26 +01:00
2019-03-22 16:00:01 +01:00
if (( int ) $node [ 'id_parent' ] > 0 ) {
2019-03-22 13:16:26 +01:00
$parent_node = $this -> nodes [ $parent_id ][ 'id_node' ];
}
2019-03-17 01:39:56 +01:00
// Store relationship.
2019-03-22 16:00:01 +01:00
if ( is_integer ( $parent_node ) && $node [ 'id_parent' ] > 0 ) {
2019-03-18 18:11:54 +01:00
$rel = [];
// Node reference (parent).
$rel [ 'id_parent' ] = $parent_node ;
$rel [ 'parent_type' ] = NODE_AGENT ;
$rel [ 'id_parent_source_data' ] = $node [ 'id_parent' ];
// Node reference (child).
$rel [ 'id_child' ] = $node [ 'id_node' ];
$rel [ 'child_type' ] = NODE_AGENT ;
$rel [ 'id_child_source_data' ] = $node [ 'id_agente' ];
// Store relation.
$relations [] = $rel ;
2019-03-17 01:39:56 +01:00
}
break ;
2019-03-15 20:44:57 +01:00
2019-03-17 01:39:56 +01:00
case NODE_MODULE :
// Search for module relationships.
$module_relations = modules_get_relations (
2019-03-18 18:11:54 +01:00
[ 'id_module' => $node [ 'id_agente_modulo' ]]
2019-03-17 01:39:56 +01:00
);
2019-03-18 18:11:54 +01:00
2019-03-17 01:39:56 +01:00
if ( $module_relations !== false ) {
2019-03-18 18:11:54 +01:00
// Module relation exist.
foreach ( $module_relations as $mod_rel ) {
// Check if target referenced agent is defined in
// current map.
$agent_a = modules_get_agentmodule_agent (
$mod_rel [ 'module_a' ]
);
$module_a = $mod_rel [ 'module_a' ];
$agent_b = modules_get_agentmodule_agent (
$mod_rel [ 'module_b' ]
);
$module_b = $mod_rel [ 'module_b' ];
// Calculate target.
$module_to = $module_a ;
$agent_to = $agent_a ;
$module_from = $module_b ;
$agent_from = $agent_b ;
// Module relations does not have from and to,
// If current agent_a is current node, reverse relation.
if ( $agent_a == $node [ 'id_agente' ]) {
$module_to = $module_b ;
$agent_to = $agent_b ;
$module_from = $module_a ;
$agent_from = $agent_a ;
}
2019-03-17 01:39:56 +01:00
2019-03-18 18:11:54 +01:00
$target_node = $this -> nodes [ NODE_AGENT . '_' . $agent_to ];
2019-03-17 01:39:56 +01:00
2019-03-18 18:11:54 +01:00
if ( isset ( $target_node ) === false ) {
// Agent is not present in this map.
2019-03-17 01:39:56 +01:00
continue ;
}
2019-03-18 18:11:54 +01:00
$rel = [];
// Node reference (child).
$rel [ 'id_child' ] = $node [ 'id_node' ];
$rel [ 'child_type' ] = NODE_MODULE ;
$rel [ 'id_child_source_data' ] = $module_from ;
$rel [ 'id_child_agent' ] = $agent_from ;
// Node reference (parent).
$rel [ 'id_parent' ] = $target_node [ 'id_node' ];
$rel [ 'parent_type' ] = NODE_MODULE ;
$rel [ 'id_parent_source_data' ] = $module_to ;
$rel [ 'id_parent_agent' ] = $agent_to ;
// Store relation.
$relations [] = $rel ;
2019-03-17 01:39:56 +01:00
}
}
break ;
case NODE_GENERIC :
// Handmade ones.
// Add also parent relationship.
2019-03-29 20:31:55 +01:00
if ( isset ( $node [ 'id_parent' ])) {
2020-05-21 19:28:24 +02:00
$parent_id = NODE_AGENT . '_' . $node [ 'id_parent' ];
$parent_node = $this -> nodes [ $parent_id ][ 'id_node' ];
2019-03-22 13:16:26 +01:00
2020-05-21 19:28:24 +02:00
if ( $parent_node === null ) {
$parent_id = NODE_MODULE . '_' . $node [ 'id_parent' ];
$parent_node = $this -> nodes [ $parent_id ][ 'id_node' ];
}
if ( $parent_node === null ) {
$parent_id = NODE_GENERIC . '_' . $node [ 'id_parent' ];
$parent_node = $this -> nodes [ $parent_id ][ 'id_node' ];
2019-03-29 20:31:55 +01:00
}
2019-03-17 01:39:56 +01:00
2019-03-29 20:31:55 +01:00
// Store relationship.
if ( $parent_node !== null ) {
$relations [] = [
'id_parent' => $parent_node ,
'parent_type' => NODE_GENERIC ,
'id_child' => $node [ 'id_node' ],
'child_type' => NODE_GENERIC ,
];
}
2019-03-17 01:39:56 +01:00
}
break ;
case NODE_PANDORA :
default :
// Ignore.
break ;
2019-03-15 20:44:57 +01:00
}
// Others.
return $relations ;
}
2019-03-12 16:22:28 +01:00
/**
2019-03-19 20:43:08 +01:00
* Generates or loads nodes & relations array from DB .
* Load , calculates statuses and leave the structure in $this -> graph .
*
* * Structure generated :
* Nodes :
* id_map .
* id .
* id_agent .
* id_module .
* type .
* x .
* y .
* width .
* height .
* text .
* source_data .
* style ( json ) .
*
* Relations :
* id_map .
* id_parent .
* parent_type .
* id_parent_source_data .
* id_child .
* child_type .
* id_child_source_data .
* id_parent_agent .
* id_child_agent .
2019-03-12 16:22:28 +01:00
*
* @ return void
*/
public function loadGraph ()
{
$nodes = $this -> nodes ;
$relations = $this -> relations ;
// Generate if there's no data in DB about nodes or relations.
2021-09-23 17:01:22 +02:00
if ( empty ( $nodes ) === true && empty ( $relations ) === true ) {
2019-03-12 16:22:28 +01:00
$this -> generateNetworkMap ();
return ;
}
2021-09-23 17:01:22 +02:00
$graph = networkmap_load_map ( $this );
2019-03-19 20:43:08 +01:00
2021-09-23 17:01:22 +02:00
if ( empty ( $graph ) === true ) {
2019-03-20 13:10:20 +01:00
$this -> generateNetworkMap ();
return ;
2019-03-12 16:22:28 +01:00
}
2019-03-19 20:43:08 +01:00
$this -> graph = $graph ;
2019-03-12 16:22:28 +01:00
}
2019-03-15 20:44:57 +01:00
/**
* Generates a graph definition ( header only ) for dot graph .
*
* @ return string Dot graph header .
*/
public function openDotFile ()
{
global $config ;
$overlap = 'compress' ;
$map_filter = $this -> mapOptions [ 'map_filter' ];
$nooverlap = $this -> mapOptions [ 'nooverlap' ];
2019-03-19 20:43:08 +01:00
$zoom = $this -> mapOptions [ 'zoom' ];
2020-05-21 19:28:24 +02:00
$layout = $this -> mapOptions [ 'layout' ];
2019-03-15 20:44:57 +01:00
2019-03-22 03:56:31 +01:00
if ( isset ( $this -> mapOptions [ 'width' ])
&& isset ( $this -> mapOptions [ 'height' ])
) {
$size_x = ( $this -> mapOptions [ 'width' ] / 100 );
$size_y = ( $this -> mapOptions [ 'height' ] / 100 );
} else if ( isset ( $config [ 'networkmap_max_width' ])) {
2019-03-15 20:44:57 +01:00
$size_x = ( $config [ 'networkmap_max_width' ] / 100 );
$size_y = ( $size_x * 0.8 );
} else {
$size_x = 8 ;
$size_y = 5.4 ;
$size = '' ;
}
if ( $zoom > 0 ) {
$size_x *= $zoom ;
$size_y *= $zoom ;
}
$size = $size_x . ',' . $size_y ;
2020-05-21 19:28:24 +02:00
if ( $this -> mapOptions [ 'size_canvas' ] !== null ) {
2019-03-15 20:44:57 +01:00
$size = ( $this -> mapOptions [ 'size_canvas' ][ 'x' ] / 100 );
$size .= ',' . ( $this -> mapOptions [ 'size_canvas' ][ 'y' ] / 100 );
}
2019-03-17 01:39:56 +01:00
// Graphviz custom values.
2019-03-15 20:44:57 +01:00
if ( isset ( $map_filter [ 'node_sep' ])) {
$node_sep = $map_filter [ 'node_sep' ];
} else {
$node_sep = 0.1 ;
}
if ( isset ( $map_filter [ 'rank_sep' ])) {
$rank_sep = $map_filter [ 'rank_sep' ];
} else {
if ( $layout == 'radial' ) {
$rank_sep = 1.0 ;
} else {
$rank_sep = 0.5 ;
}
}
if ( isset ( $map_filter [ 'mindist' ])) {
$mindist = $map_filter [ 'mindist' ];
} else {
$mindist = 1.0 ;
}
if ( isset ( $map_filter [ 'kval' ])) {
$kval = $map_filter [ 'kval' ];
} else {
$kval = 0.1 ;
}
// BEWARE: graphwiz DONT use single ('), you need double (").
$head = 'graph networkmap { dpi=100; bgcolor="transparent"; labeljust=l; margin=0; pad="0.75,0.75";' ;
if ( $nooverlap != '' ) {
$head .= 'overlap=scale;' ;
$head .= 'outputorder=first;' ;
}
if ( $layout == 'flat'
|| $layout == 'spring1'
|| $layout == 'spring2'
) {
if ( $nooverlap != '' ) {
$head .= 'overlap="scalexy";' ;
}
if ( $layout == 'flat' ) {
$head .= 'ranksep="' . $rank_sep . '";' ;
}
if ( $layout == 'spring2' ) {
$head .= 'K="' . $kval . '";' ;
}
}
if ( $layout == 'radial' ) {
$head .= 'ranksep="' . $rank_sep . '";' ;
}
if ( $layout == 'circular' ) {
$head .= 'mindist="' . $mindist . '";' ;
}
$head .= 'ratio="fill";' ;
$head .= 'root=0;' ;
$head .= 'nodesep="' . $node_sep . '";' ;
$head .= 'size="' . $size . '";' ;
$head .= " \n " ;
return $head ;
}
/**
* Creates a node in dot format .
* Requirements :
* id_node
* id_source
* status => defines 'color'
* label
* image
* url
*
* @ param array $data Node definition .
*
* @ return string Dot node .
*/
public function createDotNode ( $data )
{
global $config ;
2019-03-17 01:39:56 +01:00
if ( is_array ( $data ) === false ) {
return '' ;
}
2019-03-15 20:44:57 +01:00
2019-04-08 18:28:27 +02:00
if ( $this -> mapOptions [ 'fixed_positions' ]) {
// Ignore.
return ;
}
2019-03-15 20:44:57 +01:00
$dot_str = '' ;
2019-03-18 18:11:54 +01:00
// Color is being printed by D3, not graphviz.
// Used only for positioning.
2019-03-15 20:44:57 +01:00
$color = COL_NORMAL ;
$label = $data [ 'label' ];
$url = 'none' ;
$parent = $data [ 'parent' ];
$font_size = $this -> mapOptions [ 'font_size' ];
2019-03-29 20:31:55 +01:00
if ( isset ( $data [ 'radius' ])) {
$radius = $data [ 'radius' ];
} else {
$radius = $this -> mapOptions [ 'map_filter' ][ 'node_radius' ];
}
$radius /= GRAPHVIZ_CONVERSION_FACTOR ;
2019-03-15 20:44:57 +01:00
2019-04-08 18:28:27 +02:00
if ( is_array ( $label )) {
2020-05-21 19:28:24 +02:00
$label = join ( '' , $label );
2019-04-08 18:28:27 +02:00
}
2019-03-15 20:44:57 +01:00
if ( strlen ( $label ) > 16 ) {
$label = ui_print_truncate_text ( $label , 16 , false , true , false );
}
// If radius is 0, set to 1 instead.
if ( $radius <= 0 ) {
$radius = 1 ;
}
// Simple node always. This kind of node is used only to
// retrieve X,Y positions from graphviz no for personalization.
$dot_str = $data [ 'id_node' ] . ' [ parent="' . $data [ 'id_parent' ] . '"' ;
$dot_str .= ', color="' . $color . '", fontsize=' . $font_size ;
2020-05-21 19:28:24 +02:00
$dot_str .= ', shape="doublecircle"' . $data [ 'url_node_link' ];
2019-03-17 01:39:56 +01:00
$dot_str .= ', style="filled", fixedsize=true, width=' . $radius ;
$dot_str .= ', height=' . $radius . ', label="' . $label . '"]' . " \n " ;
2019-03-15 20:44:57 +01:00
return $dot_str ;
}
2019-03-19 20:43:08 +01:00
/**
* Avoid multiple connections between two nodes if any of them does not
* add more information . Prioritize .
*
* For instance , if we have module - module relationship and agent - agent
* discard agent - agent relationship ( module - module apports more
* information ) .
*
* @ return void
*/
public function cleanGraphRelations ()
{
global $config ;
$relations = $this -> graph [ 'relations' ];
2019-03-20 17:22:06 +01:00
$cleaned = [];
$rel_map = [];
2019-03-19 20:43:08 +01:00
2019-03-20 17:22:06 +01:00
/*
* Relation map :
* id_child . '_' . id_parent => [
* 'priority' ( 0 , 1 )
* 'relation_index'
* ]
*/
2019-03-19 20:43:08 +01:00
2019-03-22 03:56:31 +01:00
if ( is_array ( $relations )) {
foreach ( $relations as $index => $rel ) {
/*
* AA , AM and MM links management
* Priority :
* 1 -> MM ( module - module )
* 1 -> AM ( agent - module )
* 0 -> AA ( agent - agent )
*/
$id_parent = $rel [ 'id_parent' ];
$id_child = $rel [ 'id_child' ];
$rel_type = $rel [ 'child_type' ] . '_' . $rel [ 'parent_type' ];
$valid = 0 ;
$key = - 1 ;
if ( $rel [ 'parent_type' ] == NODE_MODULE
&& $rel [ 'child_type' ] == NODE_MODULE
) {
2020-01-15 14:11:36 +01:00
// Keep std references.
$ref_id_parent = $id_parent ;
$ref_id_child = $id_child ;
2019-03-22 03:56:31 +01:00
// Module information available.
2019-12-11 16:42:50 +01:00
$id_parent = $rel [ 'id_parent_source_data' ];
$id_child = $rel [ 'id_child_source_data' ];
2019-03-22 03:56:31 +01:00
$priority = 1 ;
$valid = 1 ;
if ( is_array ( $rel_map [ $id_child . '_' . $id_parent ])) {
// Already defined.
$key = $id_child . '_' . $id_parent ;
$data = $rel_map [ $id_child . '_' . $id_parent ];
if ( $priority > $data [ 'priority' ]) {
unset ( $rel [ $data [ 'index' ]]);
} else {
$valid = 0 ;
}
2019-03-19 20:43:08 +01:00
}
2019-03-22 03:56:31 +01:00
if ( is_array ( $rel_map [ $id_parent . '_' . $id_child ])) {
// Already defined.
$key = $id_parent . '_' . $id_child ;
$data = $rel_map [ $id_parent . '_' . $id_child ];
if ( $priority > $data [ 'priority' ]) {
unset ( $rel [ $data [ 'index' ]]);
} else {
$valid = 0 ;
}
2019-03-19 20:43:08 +01:00
}
2019-03-22 03:56:31 +01:00
if ( $valid == 1 ) {
$rel_map [ $id_parent . '_' . $id_child ] = [
'index' => $index ,
'priority' => $priority ,
];
2020-01-15 14:11:36 +01:00
// Keep node reference mapping - low precedence relationship.
$rel_map [ $ref_id_parent . '_' . $ref_id_child ] = [
'index' => $index ,
'priority' => $priority ,
];
2019-03-22 03:56:31 +01:00
}
} else if ( $rel [ 'parent_type' ] == NODE_AGENT
&& $rel [ 'child_type' ] == NODE_AGENT
) {
// Module information not available.
$priority = 0 ;
$valid = 1 ;
if ( is_array ( $rel_map [ $id_child . '_' . $id_parent ])) {
// Already defined.
$key = $id_child . '_' . $id_parent ;
$data = $rel_map [ $id_child . '_' . $id_parent ];
if ( $priority > $data [ 'priority' ]) {
unset ( $rel [ $data [ 'index' ]]);
} else {
$valid = 0 ;
}
2019-03-19 20:43:08 +01:00
}
2019-03-22 03:56:31 +01:00
if ( is_array ( $rel_map [ $id_parent . '_' . $id_child ])) {
// Already defined.
$key = $id_parent . '_' . $id_child ;
$data = $rel_map [ $id_parent . '_' . $id_child ];
if ( $priority > $data [ 'priority' ]) {
unset ( $rel [ $data [ 'index' ]]);
} else {
$valid = 0 ;
}
2019-03-19 20:43:08 +01:00
}
2019-03-22 03:56:31 +01:00
if ( $valid == 1 ) {
$rel_map [ $id_parent . '_' . $id_child ] = [
'index' => $index ,
'priority' => $priority ,
];
}
} else if ( $rel [ 'parent_type' ] == NODE_MODULE
&& $rel [ 'child_type' ] == NODE_AGENT
) {
// Module information not available.
$priority = 1 ;
2019-03-19 20:43:08 +01:00
2019-03-22 03:56:31 +01:00
$valid = 1 ;
} else if ( $rel [ 'parent_type' ] == NODE_AGENT
&& $rel [ 'child_type' ] == NODE_MODULE
) {
// Module information not available.
$priority = 1 ;
2019-03-19 20:43:08 +01:00
2019-03-22 03:56:31 +01:00
$valid = 1 ;
} else {
// Pandora & generic links are always accepted.
$valid = 1 ;
}
2019-03-19 20:43:08 +01:00
2019-03-22 03:56:31 +01:00
if ( $valid === 1 ) {
if ( $rel [ 'id_parent' ] != $rel [ 'id_child' ]) {
$cleaned [] = $rel ;
}
2019-03-21 21:34:56 +01:00
}
2019-03-19 20:43:08 +01:00
}
2019-03-22 03:56:31 +01:00
} else {
return ;
2019-03-19 20:43:08 +01:00
}
2019-03-20 17:22:06 +01:00
$this -> graph [ 'relations' ] = $cleaned ;
2019-03-19 20:43:08 +01:00
}
/**
* Internal method to allow developer to compare status from
* different origins by checking a value .
*
* Greater value implies more critical .
*
* @ param integer $status Status .
*
* @ return integer Criticity value .
*/
private static function getStatusNumeric ( $status )
{
if ( isset ( $status ) === false ) {
return NO_CRIT ;
}
switch ( $status ) {
case AGENT_MODULE_STATUS_NORMAL :
case AGENT_STATUS_NORMAL :
return CRIT_1 ;
case AGENT_MODULE_STATUS_NOT_INIT :
case AGENT_STATUS_NOT_INIT :
return CRIT_0 ;
case AGENT_MODULE_STATUS_CRITICAL_BAD :
case AGENT_STATUS_CRITICAL :
return CRIT_4 ;
case AGENT_MODULE_STATUS_WARNING :
case AGENT_STATUS_WARNING :
return CRIT_3 ;
case AGENT_MODULE_STATUS_CRITICAL_ALERT :
case AGENT_MODULE_STATUS_WARNING_ALERT :
case AGENT_STATUS_ALERT_FIRED :
return CRIT_5 ;
case AGENT_MODULE_STATUS_UNKNOWN :
case AGENT_STATUS_UNKNOWN :
return CRIT_2 ;
default :
// Ignored.
break ;
}
return NO_CRIT ;
}
/**
* Returns worst status from two received .
* Agent and module statuses should be identical , unless little differences .
*
* @ param integer $status_a Status A .
* @ param integer $status_b Status B .
*
* @ return integer Status A or status B , the worstest one .
*/
public static function getWorstStatus ( $status_a , $status_b )
{
// Case agent statuses.
$a = self :: getStatusNumeric ( $status_a );
$b = self :: getStatusNumeric ( $status_b );
return ( $a > $b ) ? $status_a : $status_b ;
}
2019-03-17 01:39:56 +01:00
/**
* Returns target color to be used based on the status received .
*
2020-05-22 12:14:01 +02:00
* @ param integer $status Source information .
* @ param boolean $force_module It ' s a module .
2019-03-17 01:39:56 +01:00
*
* @ return string HTML tag for color .
*/
2020-05-22 12:14:01 +02:00
public static function getColorByStatus ( $status , ? bool $force_module = false )
2019-03-17 01:39:56 +01:00
{
2019-05-28 12:13:29 +02:00
include_once __DIR__ . '/../functions_modules.php' ;
2020-05-22 12:14:01 +02:00
return modules_get_color_status ( $status , $force_module );
2019-03-17 01:39:56 +01:00
}
/**
* Translates a standard node into a JS node with following attributes :
*
2019-03-19 20:43:08 +01:00
* @ param array $nodes Input array ( standard nodes structure ) .
2019-03-17 01:39:56 +01:00
* id_map .
2019-03-19 20:43:08 +01:00
* id_db .
2019-03-17 01:39:56 +01:00
* type .
* source_data .
* x .
* y .
* z .
* state .
* deleted .
* style .
* shape .
* image .
* label .
* id_agent .
* id_networkmap .
*
* @ return array Object ready to be dump to JS .
* * Output array ( translated ) :
* id .
* id_db .
* type .
* id_agent .
* id_module .
* fixed .
* x .
* y .
* px .
* py .
* z .
* state .
* deleted .
* image_url .
* image_width .
* image_height .
* raw_text .
* text .
* shape .
* color .
* map_id .
* networkmap_id .
*/
2019-03-19 20:43:08 +01:00
public function nodesToJS ( $nodes )
2019-03-17 01:39:56 +01:00
{
global $config ;
2019-03-19 20:43:08 +01:00
$return = [];
2020-05-21 19:28:24 +02:00
$count_item_holding_area = 0 ;
2019-03-19 20:43:08 +01:00
foreach ( $nodes as $node ) {
$item = [];
$item [ 'id' ] = $node [ 'id' ];
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
if ( $node [ 'deleted' ]) {
// Skip deleted nodes.
continue ;
}
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
// Id titem.
2019-03-20 13:10:20 +01:00
if ( isset ( $this -> map [ '__simulated' ]) === false ) {
2019-03-19 20:43:08 +01:00
$item [ 'id_db' ] = $node [ 'id_db' ];
} else {
$item [ 'id_db' ] = ( int ) $node [ 'id' ];
}
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
// Get source data.
$source_data = $this -> getNodeData ( $node [ 'id' ]);
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
if ( is_array ( $node [ 'style' ]) === false ) {
$node [ 'style' ] = json_decode ( $node [ 'style' ], true );
2019-04-05 16:43:36 +02:00
// Add styles.
if ( isset ( $source_data [ 'style' ]) === true
&& is_array ( $source_data [ 'style' ]) === true
) {
$node [ 'style' ] = array_merge (
$node [ 'style' ],
$source_data [ 'style' ]
);
}
2019-03-19 20:43:08 +01:00
}
2019-03-17 01:39:56 +01:00
2019-03-29 20:52:51 +01:00
// Propagate styles.
foreach ( $node [ 'style' ] as $k => $v ) {
$item [ $k ] = $v ;
}
2019-03-19 20:43:08 +01:00
$item [ 'type' ] = $node [ 'type' ];
$item [ 'fixed' ] = true ;
$item [ 'x' ] = ( int ) $node [ 'x' ];
$item [ 'y' ] = ( int ) $node [ 'y' ];
$item [ 'z' ] = ( int ) $node [ 'z' ];
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
// X,Y aliases for D3.
$item [ 'px' ] = $item [ 'x' ];
$item [ 'py' ] = $item [ 'y' ];
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
// Status represents the status of the node (critical, warning...).
// State represents state of node in map (in holding_area or not).
$item [ 'state' ] = $node [ 'state' ];
$item [ 'deleted' ] = $node [ 'deleted' ];
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
// Node color.
$item [ 'color' ] = self :: getColorByStatus ( $source_data [ 'status' ]);
switch ( $node [ 'type' ]) {
case NODE_AGENT :
$item [ 'id_agent' ] = $node [ 'source_data' ];
break ;
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
case NODE_MODULE :
$item [ 'id_module' ] = $node [ 'source_data' ];
2020-05-22 12:14:01 +02:00
$item [ 'color' ] = self :: getColorByStatus (
$source_data [ 'status' ],
true
);
2019-03-19 20:43:08 +01:00
break ;
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
case NODE_PANDORA :
$item [ 'color' ] = COL_IGNORED ;
$node [ 'style' ][ 'image' ] = ui_get_logo_to_center_networkmap ();
break ;
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
case NODE_GENERIC :
default :
2019-03-21 16:16:53 +01:00
foreach ( $source_data as $k => $v ) {
$node [ $k ] = $v ;
2020-05-21 19:28:24 +02:00
$item [ $k ] = $v ;
2019-03-21 16:16:53 +01:00
}
2020-05-21 19:28:24 +02:00
$item [ 'id_agent' ] = $node [ 'id_agente' ];
2019-04-30 17:30:57 +02:00
if ( ! empty ( $node [ 'text' ])) {
$node [ 'style' ][ 'label' ] = $node [ 'text' ];
} else {
$node [ 'style' ][ 'label' ] = $node [ 'name' ];
}
2019-03-29 20:52:51 +01:00
if ( isset ( $source_data [ 'color' ])) {
$item [ 'color' ] = $source_data [ 'color' ];
} else {
$item [ 'color' ] = self :: getColorByStatus (
2020-05-22 12:14:01 +02:00
$node [ 'status' ],
( bool ) $node [ 'id_module' ]
2019-03-29 20:52:51 +01:00
);
}
2019-03-19 20:43:08 +01:00
break ;
}
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
// Calculate values.
// 40 => DEFAULT NODE RADIUS.
// 30 => alignment factor.
$holding_area_max_y = ( $this -> mapOptions [ 'height' ] + 30 + $this -> mapOptions [ 'map_filter' ][ 'node_radius' ] * 2 - $this -> mapOptions [ 'map_filter' ][ 'holding_area' ][ 1 ] + 10 * $this -> mapOptions [ 'map_filter' ][ 'node_radius' ]);
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
// Update position if node must be stored in holding_area.
if ( $item [ 'state' ] == 'holding_area' ) {
$holding_area_x = ( $this -> mapOptions [ 'width' ] + 30 + $this -> mapOptions [ 'map_filter' ][ 'node_radius' ] * 2 - $this -> mapOptions [ 'map_filter' ][ 'holding_area' ][ 0 ] + ( $count_item_holding_area % 11 ) * $this -> mapOptions [ 'map_filter' ][ 'node_radius' ]);
$holding_area_y = ( $this -> mapOptions [ 'height' ] + 30 + $this -> mapOptions [ 'map_filter' ][ 'node_radius' ] * 2 - $this -> mapOptions [ 'map_filter' ][ 'holding_area' ][ 1 ] + ( int ) (( $count_item_holding_area / 11 )) * $this -> mapOptions [ 'map_filter' ][ 'node_radius' ]);
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
// Keep holding area nodes in holding area.
if ( $holding_area_max_y <= $holding_area_y ) {
$holding_area_y = $holding_area_max_y ;
}
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
$item [ 'x' ] = $holding_area_x ;
$item [ 'y' ] = $holding_area_y ;
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
// Increment for the next node in holding area.
$count_item_holding_area ++ ;
}
2019-03-17 01:39:56 +01:00
2019-03-19 20:43:08 +01:00
// Node image.
$item [ 'image_url' ] = '' ;
$item [ 'image_width' ] = 0 ;
$item [ 'image_height' ] = 0 ;
if ( empty ( $node [ 'style' ][ 'image' ]) === false ) {
$item [ 'image_url' ] = ui_get_full_url (
2021-04-06 16:47:32 +02:00
$node [ 'style' ][ 'image' ],
false ,
false ,
false
2019-03-19 20:43:08 +01:00
);
$image_size = getimagesize (
$config [ 'homedir' ] . '/' . $node [ 'style' ][ 'image' ]
);
$item [ 'image_width' ] = ( int ) $image_size [ 0 ];
$item [ 'image_height' ] = ( int ) $image_size [ 1 ];
}
$item [ 'raw_text' ] = $node [ 'style' ][ 'label' ];
$item [ 'text' ] = io_safe_output ( $node [ 'style' ][ 'label' ]);
$item [ 'shape' ] = $node [ 'style' ][ 'shape' ];
$item [ 'map_id' ] = $node [ 'id_map' ];
2019-03-29 20:31:55 +01:00
2019-03-19 20:43:08 +01:00
if ( ! isset ( $node [ 'style' ][ 'id_networkmap' ])
|| $node [ 'style' ][ 'id_networkmap' ] == ''
|| $node [ 'style' ][ 'id_networkmap' ] == 0
) {
$item [ 'networkmap_id' ] = 0 ;
} else {
$item [ 'networkmap_id' ] = $node [ 'style' ][ 'id_networkmap' ];
}
2019-03-22 03:56:31 +01:00
// XXX: Compatibility with Tooltipster - Simple map controller.
if ( $this -> useTooltipster ) {
$item [ 'label' ] = $item [ 'text' ];
$item [ 'image' ] = $item [ 'image_url' ];
$item [ 'image_height' ] = 52 ;
$item [ 'image_width' ] = 52 ;
}
2019-03-19 20:43:08 +01:00
$return [] = $item ;
2019-03-17 01:39:56 +01:00
}
2019-03-19 20:43:08 +01:00
return $return ;
2019-03-17 01:39:56 +01:00
}
/**
* Transforms an edge relationship into a JS array to be dumped .
2019-03-19 20:43:08 +01:00
* Sets fields like status , link color and updates some internal identifiers
* used by JS frontend .
2019-03-17 01:39:56 +01:00
*
2019-03-19 20:43:08 +01:00
* @ param array $edges Edges information in array of following items .
2019-03-17 01:39:56 +01:00
*
* * Input structure :
2019-03-19 20:43:08 +01:00
* id_map .
* id_parent .
2019-03-17 01:39:56 +01:00
* parent_type .
* id_parent_source_data .
2019-03-19 20:43:08 +01:00
* id_child .
* child_type .
2019-03-17 01:39:56 +01:00
* id_child_source_data .
2019-03-19 20:43:08 +01:00
* id_parent_agent .
* id_child_agent .
2019-03-17 01:39:56 +01:00
*
* @ return array Edge translated to JS object .
*
* * Output structure :
* arrow_start .
* arrow_end .
* status_start .
* status_end .
* id_module_start .
* id_agent_start .
* id_module_end .
* id_agent_end .
* link_color .
* target .
* source .
* deleted .
* target_id_db .
* source_id_db .
* text_start .
* text_end .
*/
2019-03-19 20:43:08 +01:00
public function edgeToJS ( $edges )
2019-03-17 01:39:56 +01:00
{
2019-03-19 20:43:08 +01:00
$return = [];
// JS edge pseudo identificator.
$i = 0 ;
foreach ( $edges as $rel ) {
$item = [];
// Simulated index.
$item [ 'id_db' ] = $i ;
$item [ 'deleted' ] = 0 ;
// Else load.
if ( isset ( $this -> map [ '__simulated' ]) === false ) {
$item [ 'id_db' ] = $rel [ 'id_db' ];
$item [ 'deleted' ] = $rel [ 'deleted' ];
2019-03-20 13:10:20 +01:00
$item [ 'target_id_db' ] = $this -> getNodeData (
$rel [ 'id_parent' ],
'id_db'
);
$item [ 'source_id_db' ] = $this -> getNodeData (
$rel [ 'id_child' ],
'id_db'
);
}
if ( $item [ 'deleted' ]) {
// Relation is deleted. Avoid.
continue ;
2019-03-19 20:43:08 +01:00
}
// Set relationship as 'agent' by default.
// Generic and Pandora nodes simulates agent relationships.
$item [ 'arrow_start' ] = 'agent' ;
$item [ 'arrow_end' ] = 'agent' ;
$item [ 'source' ] = $rel [ 'id_parent' ];
$item [ 'target' ] = $rel [ 'id_child' ];
$item [ 'id_agent_start' ] = $rel [ 'id_child_agent' ];
$item [ 'id_agent_end' ] = $rel [ 'id_parent_agent' ];
2019-03-20 13:10:20 +01:00
if ( $rel [ 'parent_type' ] == NODE_MODULE ) {
2019-03-19 20:43:08 +01:00
$item [ 'arrow_start' ] = 'module' ;
$item [ 'id_module_start' ] = $rel [ 'id_parent_source_data' ];
$item [ 'status_start' ] = modules_get_agentmodule_status (
$item [ 'id_module_start' ]
);
// Extract interface name to be placed on edge.
$text = modules_get_agentmodule_name (
( int ) $item [ 'id_module_start' ]
);
if ( preg_match (
'/(.+)_ifOperStatus$/' ,
( string ) $text ,
$matches
)
) {
if ( $matches [ 1 ]) {
$item [ 'text_start' ] = io_safe_output ( $matches [ 1 ]);
}
}
}
2019-03-20 13:10:20 +01:00
if ( $rel [ 'child_type' ] == NODE_MODULE ) {
2019-03-19 20:43:08 +01:00
$item [ 'arrow_end' ] = 'module' ;
$item [ 'id_module_end' ] = $rel [ 'id_child_source_data' ];
$item [ 'status_end' ] = modules_get_agentmodule_status (
$item [ 'id_module_end' ]
);
// Extract interface name to be placed on edge.
$text = modules_get_agentmodule_name (
( int ) $item [ 'id_module_end' ]
);
if ( preg_match (
'/(.+)_ifOperStatus$/' ,
( string ) $text ,
$matches
)
) {
if ( $matches [ 1 ]) {
$item [ 'text_end' ] = io_safe_output ( $matches [ 1 ]);
}
}
}
2019-03-22 15:08:44 +01:00
if ( isset ( $rel [ 'text_start' ]) && ! empty ( $rel [ 'text_start' ])) {
// Direct text_start definition.
$item [ 'text_start' ] = $rel [ 'text_start' ];
}
if ( isset ( $rel [ 'text_end' ]) && ! empty ( $rel [ 'text_end' ])) {
// Direct text_end definition.
$item [ 'text_end' ] = $rel [ 'text_end' ];
}
2019-03-22 15:06:01 +01:00
if ( isset ( $rel [ 'link_color' ]) && ! empty ( $rel [ 'link_color' ])) {
2019-03-22 15:00:02 +01:00
// Direct color definition.
$item [ 'link_color' ] = $rel [ 'link_color' ];
} else {
// Use worst case to set link color.
$item [ 'link_color' ] = self :: getColorByStatus (
self :: getWorstStatus (
$item [ 'status_start' ],
$item [ 'status_end' ]
)
);
}
2019-03-19 20:43:08 +01:00
2019-03-22 03:56:31 +01:00
// XXX: Compatibility with Tooltipster - Simple map controller.
if ( $this -> useTooltipster ) {
$item [ 'orig' ] = $rel [ 'id_parent' ];
$item [ 'dest' ] = $rel [ 'id_child' ];
}
2019-03-19 20:43:08 +01:00
// Set direct values.
$item [ 'id' ] = $i ++ ;
$return [] = $item ;
}
return $return ;
2019-03-17 01:39:56 +01:00
}
2019-03-15 20:44:57 +01:00
/**
* Creates an edge in dot format .
* Requirements :
* from
* to
*
* @ param array $data Edge content .
*
* @ return string Dot code for given edge .
*/
public function createDotEdge ( $data )
{
if ( is_array ( $data ) === false ) {
return '' ;
}
if ( ! isset ( $data [ 'from' ]) || ! isset ( $data [ 'to' ])) {
return '' ;
}
$edge = " \n " . $data [ 'from' ] . ' -- ' . $data [ 'to' ];
2019-03-21 16:16:53 +01:00
$edge .= '[len=' . $this -> mapOptions [ 'map_filter' ][ 'node_sep' ];
2019-03-15 20:44:57 +01:00
$edge .= ', color="#BDBDBD", headclip=false, tailclip=false,' ;
$edge .= ' edgeURL=""];' . " \n " ;
return $edge ;
}
/**
* Returns dot file end string .
*
* @ return string Dot file end string .
*/
public function closeDotFile ()
{
return '}' ;
}
2019-03-12 12:05:54 +01:00
/**
* Generate a graphviz string structure to be used later .
*
2019-03-17 01:39:56 +01:00
* Usage :
* To create a new handmade graph :
* Define node struture
* key => node source data ( agent / module row or custom )
*
* Minimum required fields in array :
* label
* status
* id
*
* @ param array $nodes Generate dotgraph using defined nodes .
*
2019-03-12 12:05:54 +01:00
* @ return void
*/
2019-03-17 01:39:56 +01:00
public function generateDotGraph ( $nodes = false )
2019-03-12 12:05:54 +01:00
{
if ( ! isset ( $this -> dotGraph )) {
// Generate dot file.
2019-03-17 01:39:56 +01:00
$this -> nodes = [];
2019-03-15 20:44:57 +01:00
$edges = [];
$graph = '' ;
2019-03-17 01:39:56 +01:00
if ( $nodes === false ) {
2019-03-22 03:56:31 +01:00
if ( isset ( $this -> rawNodes )) {
2019-03-21 16:16:53 +01:00
$nodes = $this -> rawNodes ;
} else {
// Search for nodes.
$nodes = $this -> calculateNodes ();
}
2019-03-17 01:39:56 +01:00
}
2019-03-15 20:44:57 +01:00
// Search for relations.
// Build dot structure.
// Open Graph.
$graph = $this -> openDotFile ();
2019-03-22 03:56:31 +01:00
if ( ! $this -> noPandoraNode ) {
// Create empty pandora node to link orphans.
$this -> nodes [ 0 ] = [
'label' => get_product_name (),
'id_node' => 0 ,
'id_agente' => 0 ,
'id_agente_modulo' => 0 ,
'node_type' => NODE_PANDORA ,
];
2019-03-17 01:39:56 +01:00
2019-03-22 03:56:31 +01:00
$this -> nodeMapping [ 0 ] = 0 ;
2019-03-17 01:39:56 +01:00
2019-03-22 03:56:31 +01:00
$graph .= $this -> createDotNode (
$this -> nodes [ 0 ]
);
$i = 1 ;
} else {
$i = 0 ;
}
2019-03-17 01:39:56 +01:00
2019-03-15 20:44:57 +01:00
// Create dot nodes.
2019-03-17 01:39:56 +01:00
$orphans = [];
2019-03-15 20:44:57 +01:00
foreach ( $nodes as $k => $node ) {
2019-03-22 14:30:50 +01:00
if (( isset ( $node [ 'type' ]) && $node [ 'type' ] == NODE_AGENT
|| isset ( $node [ 'type' ]) && $node [ 'type' ] == NODE_MODULE )
2019-03-21 16:16:53 +01:00
|| ( isset ( $node [ 'type' ]) === false
&& isset ( $node [ 'id_agente' ]) === true
&& $node [ 'id_agente' ] > 0 )
2019-03-17 01:39:56 +01:00
) {
// Origin is agent or module.
2019-03-22 14:27:53 +01:00
if ( isset ( $node [ 'type' ]) && $node [ 'type' ] == NODE_MODULE
2019-03-22 14:30:50 +01:00
|| ( isset ( $node [ 'type' ]) === false
&& isset ( $node [ 'id_agente_modulo' ]) === true
&& $node [ 'id_agente_modulo' ] > 0 )
2019-03-17 01:39:56 +01:00
) {
$k = NODE_MODULE . '_' . $k ;
// Origin is module.
$id_source = $node [ 'id_agente_modulo' ];
$label = io_safe_output ( $node [ 'nombre' ]);
$status = modules_get_agentmodule_status ( $node );
$this -> nodes [ $k ][ 'node_type' ] = NODE_MODULE ;
$url = 'index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=' . $node [ 'id_agente' ];
$url_tooltip = 'ajax.php?page=operation/agentes/ver_agente&get_agentmodule_status_tooltip=1&id_module=' . $node [ 'id_agente_modulo' ];
} else {
// Origin is agent.
$k = NODE_AGENT . '_' . $k ;
$id_source = $node [ 'id_agente' ];
$label = io_safe_output ( $node [ 'alias' ]);
$status = agents_get_status_from_counts ( $node );
$this -> nodes [ $k ][ 'node_type' ] = NODE_AGENT ;
$url = 'index.php?sec=estado&sec2=operation/agentes/ver_agente&id_agente=' . $node [ 'id_agente' ];
$url_tooltip = 'ajax.php?page=operation/agentes/ver_agente&get_agent_status_tooltip=1&id_agent=' . $node [ 'id_agente' ];
}
} else {
// Handmade node.
2019-03-18 18:11:54 +01:00
// Store user node definitions.
2019-03-17 01:39:56 +01:00
$k = NODE_GENERIC . '_' . $k ;
$id_source = $node [ 'id' ];
$label = $node [ 'label' ];
$status = $node [ 'status' ];
$this -> nodes [ $k ][ 'node_type' ] = NODE_GENERIC ;
// In handmade nodes, edges are defined by using id_parent
// Referencing target parent 'id'.
$this -> nodes [ $k ][ 'id_parent' ] = $node [ 'id_parent' ];
2019-03-18 18:11:54 +01:00
$this -> nodes [ $k ][ 'width' ] = $node [ 'width' ];
$this -> nodes [ $k ][ 'height' ] = $node [ 'height' ];
$this -> nodes [ $k ][ 'id_source' ] = $node [ 'id_source' ];
$this -> nodes [ $k ][ 'shape' ] = $node [ 'shape' ];
$url = $this -> node [ 'url' ];
$url_tooltip = $this -> node [ 'url_tooltip' ];
2019-03-17 01:39:56 +01:00
}
$this -> nodes [ $k ][ 'url' ] = $url ;
$this -> nodes [ $k ][ 'url_tooltip' ] = $url_tooltip ;
// Fullfill data.
// If url is defined in node will be overwritten.
foreach ( $node as $key => $value ) {
$this -> nodes [ $k ][ $key ] = $value ;
}
2019-03-15 20:44:57 +01:00
$graph .= $this -> createDotNode (
[
'id_node' => $i ,
2019-03-17 01:39:56 +01:00
'id_source' => $id_source ,
'label' => $label ,
2019-03-15 20:44:57 +01:00
'image' => null ,
2019-04-08 18:28:27 +02:00
'radius' => max (
$node [ 'width' ],
$node [ 'height' ]
),
2019-03-15 20:44:57 +01:00
]
);
// Keep reverse reference.
2019-03-17 01:39:56 +01:00
$this -> nodeMapping [ $i ] = $k ;
2019-03-18 18:11:54 +01:00
$this -> nodes [ $k ][ 'id_source_data' ] = $id_source ;
2019-03-15 20:44:57 +01:00
$this -> nodes [ $k ][ 'id_node' ] = $i ;
2019-03-17 01:39:56 +01:00
$this -> nodes [ $k ][ 'status' ] = $status ;
2019-03-15 20:44:57 +01:00
2019-03-18 18:11:54 +01:00
// Increase for next node.
$i ++ ;
}
2019-03-22 14:43:55 +01:00
if ( ! $this -> relations ) {
// Search for relations.
foreach ( $this -> nodes as $k => $item ) {
$target = $this -> calculateRelations ( $k );
// Adopt all orphan nodes but pandora one.
if ( empty ( $target )) {
if ( isset ( $this -> noPandoraNode ) === false
|| $this -> noPandoraNode == false
) {
if ( $item [ 'id_node' ] != 0 ) {
$rel = [];
$rel [ 'id_parent' ] = 0 ;
$rel [ 'id_child' ] = $item [ 'id_node' ];
$rel [ 'parent_type' ] = NODE_PANDORA ;
$rel [ 'child_type' ] = $item [ 'node_type' ];
$rel [ 'id_child_source_data' ] = $item [ 'id_source_data' ];
$orphans [] = $rel ;
}
}
} else {
// Flattern edges.
foreach ( $target as $rel ) {
$edges [] = $rel ;
2019-03-22 13:04:53 +01:00
}
2019-03-18 18:11:54 +01:00
}
2019-03-17 01:39:56 +01:00
}
2019-03-22 14:43:55 +01:00
} else {
$edges = $this -> relations ;
2019-03-15 20:44:57 +01:00
}
2019-03-22 14:43:55 +01:00
if ( is_array ( $edges )) {
foreach ( $edges as $rel ) {
$graph .= $this -> createDotEdge (
[
'to' => $rel [ 'id_child' ],
'from' => $rel [ 'id_parent' ],
]
);
}
} else {
$edges = [];
2019-03-15 20:44:57 +01:00
}
2019-03-22 13:02:57 +01:00
if ( isset ( $this -> noPandoraNode ) === false
|| $this -> noPandoraNode == false
) {
// Add missed edges.
foreach ( $orphans as $rel ) {
$graph .= $this -> createDotEdge (
[
'from' => $rel [ 'id_child' ],
'to' => $rel [ 'id_parent' ],
]
);
}
2019-03-17 01:39:56 +01:00
2019-03-22 13:02:57 +01:00
// Store relationships.
$this -> relations = array_merge ( $edges , $orphans );
2019-03-22 16:00:01 +01:00
} else {
$this -> relations = $edges ;
2019-03-22 13:02:57 +01:00
}
2019-03-17 01:39:56 +01:00
// Close dot file.
2019-03-15 20:44:57 +01:00
$graph .= $this -> closeDotFile ();
$this -> dotGraph = $graph ;
2019-03-12 12:05:54 +01:00
}
}
2019-03-12 16:22:28 +01:00
/**
2019-03-17 01:39:56 +01:00
* Extracts node coordinates and relationships built by graphviz .
2019-03-12 16:22:28 +01:00
*
2019-03-17 01:39:56 +01:00
* @ param string $graphviz_file Graphviz output file path .
2019-03-11 20:10:08 +01:00
*
2019-03-17 01:39:56 +01:00
* @ return mixed Nodes and relations if success . False if not .
2019-03-11 20:10:08 +01:00
*/
2019-03-17 01:39:56 +01:00
private function parseGraphvizMapFile ( $graphviz_file )
2019-03-11 20:10:08 +01:00
{
2019-03-21 16:16:53 +01:00
global $config ;
2019-03-17 01:39:56 +01:00
if ( isset ( $graphviz_file ) === false
|| is_file ( $graphviz_file ) === false
) {
return false ;
}
2019-03-11 20:10:08 +01:00
2019-03-17 01:39:56 +01:00
$content = file ( $graphviz_file );
2019-03-11 20:10:08 +01:00
2019-03-17 01:39:56 +01:00
$nodes = [];
$relations = [];
2020-05-21 19:28:24 +02:00
2019-03-17 01:39:56 +01:00
foreach ( $content as $key => $line ) {
// Reduce blank spaces.
$line = preg_replace ( '/\ +/' , ' ' , $line );
if ( preg_match ( '/^graph.*$/' , $line ) != 0 ) {
// Graph definition.
$fields = explode ( ' ' , $line );
2019-03-29 20:31:55 +01:00
$this -> map [ 'width' ] = ( $fields [ 2 ] * GRAPHVIZ_CONVERSION_FACTOR );
$this -> map [ 'height' ] = ( $fields [ 3 ] * GRAPHVIZ_CONVERSION_FACTOR );
2019-03-21 16:16:53 +01:00
if ( $this -> map [ 'width' ] > $config [ 'networkmap_max_width' ]) {
$this -> map [ 'width' ] = $config [ 'networkmap_max_width' ];
}
2019-03-17 01:39:56 +01:00
2019-03-21 16:16:53 +01:00
if ( $this -> map [ 'height' ] > $config [ 'networkmap_max_width' ]) {
$this -> map [ 'height' ] = $config [ 'networkmap_max_width' ];
}
2019-03-17 01:39:56 +01:00
} else if ( preg_match ( '/^node.*$/' , $line ) != 0 ) {
// Node.
$fields = explode ( ' ' , $line );
$id = $fields [ 1 ];
2019-03-29 20:31:55 +01:00
$nodes [ $id ][ 'x' ] = ( $fields [ 2 ] * GRAPHVIZ_CONVERSION_FACTOR );
$nodes [ $id ][ 'y' ] = ( $fields [ 3 ] * GRAPHVIZ_CONVERSION_FACTOR );
2019-03-18 18:11:54 +01:00
} else if ( preg_match ( '/^edge.*$/' , $line ) != 0
&& empty ( $this -> relations ) === true
) {
2019-03-17 01:39:56 +01:00
// Edge.
// This is really not needed, because is already defined
// in $this->relations. Only for debug purposes.
$fields = explode ( ' ' , $line );
if ( strpos ( $fields [ 1 ], 'transp_' ) !== false
|| strpos ( $fields [ 2 ], 'transp_' ) !== false
) {
// Skip transparent nodes relationships.
continue ;
}
2019-03-11 20:10:08 +01:00
2019-03-17 01:39:56 +01:00
$relations [] = [
2020-05-21 19:28:24 +02:00
'id_parent' => $fields [ 1 ],
2019-03-18 18:11:54 +01:00
'parent_type' => NODE_GENERIC ,
2020-05-21 19:28:24 +02:00
'id_parent_source_data' => $fields [ 3 ],
'id_child' => $fields [ 2 ],
2019-03-18 18:11:54 +01:00
'child_type' => NODE_GENERIC ,
2020-05-21 19:28:24 +02:00
'id_child_source_data' => null ,
2019-03-17 01:39:56 +01:00
];
}
}
2019-03-11 20:10:08 +01:00
2019-03-18 18:11:54 +01:00
// Use current relationship definitions (if exists).
if ( empty ( $this -> relations ) === false ) {
$relations = $this -> relations ;
}
2019-03-17 01:39:56 +01:00
return [
'nodes' => $nodes ,
'relations' => $relations ,
];
2019-03-11 20:10:08 +01:00
2019-03-17 01:39:56 +01:00
}
2019-03-11 20:10:08 +01:00
2019-03-12 16:22:28 +01:00
2019-03-17 01:39:56 +01:00
/**
* Calculates X , Y positions foreach element defined in dotGraph .
*
* @ return array Structure parsed .
*/
public function calculateCoords ()
{
2019-03-18 18:11:54 +01:00
global $config ;
2019-03-11 20:10:08 +01:00
switch ( PHP_OS ) {
case 'WIN32' :
case 'WINNT' :
case 'Windows' :
2020-05-21 19:28:24 +02:00
$filename_dot = sys_get_temp_dir () . " \\ networkmap_ " . $this -> filter ;
2019-03-11 20:10:08 +01:00
break ;
default :
2020-05-21 19:28:24 +02:00
$filename_dot = sys_get_temp_dir () . '/networkmap_' . $this -> filter ;
2019-03-11 20:10:08 +01:00
break ;
}
2019-03-17 01:39:56 +01:00
if ( $this -> mapOptions [ 'simple' ]) {
2019-03-11 20:10:08 +01:00
$filename_dot .= '_simple' ;
}
2019-03-17 01:39:56 +01:00
if ( $this -> mapOptions [ 'nooverlap' ]) {
2019-03-11 20:10:08 +01:00
$filename_dot .= '_nooverlap' ;
}
2019-03-12 18:17:18 +01:00
$filename_dot .= uniqid () . '_' . $this -> idMap . '.dot' ;
2019-03-11 20:10:08 +01:00
2019-03-12 12:05:54 +01:00
file_put_contents ( $filename_dot , $this -> dotGraph );
2019-03-11 20:10:08 +01:00
2019-03-12 18:17:18 +01:00
$plain_file = 'plain' . uniqid () . '.txt' ;
2019-03-11 20:10:08 +01:00
switch ( PHP_OS ) {
case 'WIN32' :
case 'WINNT' :
case 'Windows' :
2019-03-12 18:17:18 +01:00
$filename_plain = sys_get_temp_dir () . '\\' . $plain_file ;
2019-03-11 20:10:08 +01:00
$cmd = io_safe_output (
2019-03-17 01:39:56 +01:00
$config [ 'graphviz_bin_dir' ] . '\\' . $this -> filter . '.exe -Tplain -o ' . $filename_plain . ' ' . $filename_dot
2019-03-11 20:10:08 +01:00
);
break ;
default :
2019-03-12 18:17:18 +01:00
$filename_plain = sys_get_temp_dir () . '/' . $plain_file ;
2019-03-11 20:10:08 +01:00
2019-03-17 01:39:56 +01:00
$cmd = $this -> filter . ' -Tplain -o ' . $filename_plain . ' ' . $filename_dot ;
2019-03-11 20:10:08 +01:00
break ;
}
2019-03-12 18:17:18 +01:00
$retval = 0 ;
$r = system ( $cmd , $retval );
if ( $retval != 0 ) {
ui_print_error_message (
__ ( 'Failed to generate dotmap, please select different layout schema' )
);
2019-03-17 01:39:56 +01:00
return [];
2019-03-12 18:17:18 +01:00
}
2019-03-11 20:10:08 +01:00
unlink ( $filename_dot );
2019-03-22 03:56:31 +01:00
if ( function_exists ( $this -> customParser )) {
try {
if ( empty ( $this -> customParserArgs )) {
$graph = call_user_func (
$this -> customParser ,
$filename_plain ,
$this -> dotGraph
);
} else {
$graph = call_user_func (
$this -> customParser ,
$filename_plain ,
$this -> dotGraph ,
$this -> customParserArgs
);
}
} catch ( Exception $e ) {
// If developer is using a custom method to parse graphviz
// results, but want to handle using default parser
// or custom based on data, it is possible to launch
// exceptions to control internal flow.
if ( $this -> fallbackDefaultParser === true ) {
$graph = $this -> parseGraphvizMapFile (
$filename_plain
);
} else {
ui_print_error_message ( $e -> getMessage ());
$graph = [];
}
}
} else {
$graph = $this -> parseGraphvizMapFile (
$filename_plain
);
}
2019-03-11 20:10:08 +01:00
unlink ( $filename_plain );
/*
* Graphviz section ends here .
*/
2019-03-17 01:39:56 +01:00
return $graph ;
}
/**
* Creates an empty dot graph ( with only base node )
*
* @ return void
*/
public function generateEmptyDotGraph ()
{
// Create an empty map dot structure.
$graph = $this -> openDotFile ();
$this -> nodes [ 0 ] = [
'label' => get_product_name (),
'id_node' => 0 ,
'id_agente' => 0 ,
'id_agente_modulo' => 0 ,
'node_type' => NODE_PANDORA ,
];
$this -> nodeMapping [ 0 ] = 0 ;
$graph .= $this -> createDotNode (
$this -> nodes [ 0 ]
);
$graph .= $this -> closeDotFile ();
$this -> dotGraph = $graph ;
}
/**
* Generates a nodes - relationships array using graphviz dot
* schema and stores nodes & relations into $this -> graph .
*
* @ return void
*/
public function generateNetworkMap ()
{
global $config ;
include_once 'include/functions_os.php' ;
$map_filter = $this -> mapOptions [ 'map_filter' ];
/*
* Let graphviz place the nodes .
*/
if ( $map_filter [ 'empty_map' ]) {
$this -> generateEmptyDotGraph ();
} else if ( ! isset ( $this -> dotGraph )) {
$this -> generateDotGraph ();
}
/*
* Calculate X , Y positions .
*/
2019-03-29 20:31:55 +01:00
if ( ! $this -> mapOptions [ 'fixed_positions' ]) {
$graph = $this -> calculateCoords ();
} else {
// Set by user.
$graph [ 'nodes' ] = $this -> rawNodes ;
2019-04-02 16:25:29 +02:00
$graph [ 'relations' ] = $this -> relations ;
2019-03-29 20:31:55 +01:00
$this -> map [ 'width' ] = $this -> mapOptions [ 'width' ];
$this -> map [ 'height' ] = $this -> mapOptions [ 'height' ];
}
2019-03-17 01:39:56 +01:00
2022-01-11 11:00:54 +01:00
if ( is_string ( $this -> map [ 'filter' ]) === true ) {
$this -> map [ 'filter' ] = json_decode ( $this -> map [ 'filter' ], true );
if ( json_last_error () !== JSON_ERROR_NONE ) {
$this -> map [ 'filter' ] = [];
}
}
2019-04-08 18:28:27 +02:00
$this -> map [ 'filter' ][ 'z_dash' ] = $this -> mapOptions [ 'z_dash' ];
2019-03-17 01:39:56 +01:00
if ( is_array ( $graph ) === true ) {
$nodes = $graph [ 'nodes' ];
$relations = $graph [ 'relations' ];
} else {
ui_print_error_message (
__ ( 'Failed to retrieve graph data.' )
);
return ;
}
2019-03-11 20:10:08 +01:00
/*
* Calculate references .
*/
$index = 0 ;
$node_center = [];
2019-03-17 01:39:56 +01:00
$graph = [];
$graph [ 'nodes' ] = [];
2019-03-15 20:44:57 +01:00
2019-03-17 01:39:56 +01:00
// Prepare graph nodes.
foreach ( $nodes as $id => $coords ) {
$node_tmp [ 'id_map' ] = $this -> idMap ;
$node_tmp [ 'id' ] = $id ;
$source = $this -> getNodeData ( $id );
2019-03-15 20:44:57 +01:00
2019-03-17 01:39:56 +01:00
$node_tmp [ 'id_agent' ] = $source [ 'id_agente' ];
2019-03-18 18:11:54 +01:00
$node_tmp [ 'id_module' ] = $source [ 'id_agente_modulo' ];
2019-03-17 01:39:56 +01:00
$node_tmp [ 'type' ] = $source [ 'node_type' ];
$node_tmp [ 'x' ] = $coords [ 'x' ];
$node_tmp [ 'y' ] = $coords [ 'y' ];
$node_tmp [ 'width' ] = $this -> mapOptions [ 'map_filter' ][ 'node_radius' ];
$node_tmp [ 'height' ] = $this -> mapOptions [ 'map_filter' ][ 'node_radius' ];
if ( isset ( $source [ 'width' ])) {
$node_tmp [ 'width' ] = $source [ 'width' ];
}
if ( isset ( $source [ 'height' ])) {
$node_tmp [ 'height' ] = $source [ 'height' ];
}
switch ( $node_tmp [ 'type' ]) {
case NODE_AGENT :
$node_tmp [ 'source_data' ] = $source [ 'id_agente' ];
$node_tmp [ 'text' ] = $source [ 'alias' ];
$node_tmp [ 'image' ] = ui_print_os_icon (
$source [ 'id_os' ],
2019-03-15 20:44:57 +01:00
false ,
true ,
true ,
true ,
true ,
true
);
2019-03-17 01:39:56 +01:00
break ;
2019-03-15 20:44:57 +01:00
2019-03-17 01:39:56 +01:00
case NODE_MODULE :
$node_tmp [ 'source_data' ] = $source [ 'id_agente_modulo' ];
$node_tmp [ 'text' ] = $source [ 'nombre' ];
$node_tmp [ 'image' ] = ui_print_moduletype_icon (
$this -> getNodeData ( $id , 'id_tipo_modulo' ),
2019-03-15 20:44:57 +01:00
true ,
true ,
false ,
true
);
2019-03-17 01:39:56 +01:00
break ;
2019-03-15 20:44:57 +01:00
2019-03-17 01:39:56 +01:00
case NODE_PANDORA :
$node_tmp [ 'text' ] = $source [ 'label' ];
$node_tmp [ 'id_agent' ] = $source [ 'id_agente' ];
$node_tmp [ 'id_module' ] = $source [ 'id_agente_modulo' ];
$node_tmp [ 'source_data' ] = 0 ;
2019-03-18 18:11:54 +01:00
$node_center [ 'x' ] = ( $coords [ 'x' ] - MAP_X_CORRECTION );
$node_center [ 'y' ] = ( $coords [ 'y' ] - MAP_Y_CORRECTION );
2019-03-17 01:39:56 +01:00
break ;
2019-03-11 20:10:08 +01:00
2019-03-17 01:39:56 +01:00
case NODE_GENERIC :
default :
$node_tmp [ 'text' ] = $source [ 'label' ];
$node_tmp [ 'id_agent' ] = $source [ 'id_agente' ];
$node_tmp [ 'id_module' ] = $source [ 'id_agente_modulo' ];
2019-03-18 18:11:54 +01:00
$node_tmp [ 'source_data' ] = $source [ 'id_source' ];
2020-05-21 19:28:24 +02:00
$node_tmp [ 'image' ] = $source [ 'image' ];
2019-03-17 01:39:56 +01:00
break ;
2019-03-11 20:10:08 +01:00
}
2019-03-17 01:39:56 +01:00
$style = [];
$style [ 'shape' ] = $source [ 'shape' ];
if ( isset ( $style [ 'shape' ]) === false ) {
$style [ 'shape' ] = 'circle' ;
2019-03-11 20:10:08 +01:00
}
2019-03-17 01:39:56 +01:00
$style [ 'image' ] = $node_tmp [ 'image' ];
$style [ 'width' ] = $node_tmp [ 'width' ];
$style [ 'height' ] = $node_tmp [ 'height' ];
2019-03-29 20:31:55 +01:00
$style [ 'radius' ] = max (
$style [ 'width' ],
$style [ 'height' ]
);
2019-03-17 01:39:56 +01:00
$style [ 'label' ] = $node_tmp [ 'text' ];
$node_tmp [ 'style' ] = json_encode ( $style );
2019-03-11 20:10:08 +01:00
2019-03-17 01:39:56 +01:00
$graph [ 'nodes' ][ $index ] = $node_tmp ;
2019-03-11 20:10:08 +01:00
$index ++ ;
}
2019-03-18 18:11:54 +01:00
// Prepare graph edges and clean double references.
2019-03-17 01:39:56 +01:00
$graph [ 'relations' ] = [];
2019-03-18 18:11:54 +01:00
$parents = [];
2019-03-17 01:39:56 +01:00
foreach ( $relations as $rel ) {
2019-03-18 18:11:54 +01:00
$tmp = [
'id_map' => $this -> idMap ,
'id_parent' => $rel [ 'id_parent' ],
'parent_type' => $rel [ 'parent_type' ],
'id_parent_source_data' => $rel [ 'id_parent_source_data' ],
'id_child' => $rel [ 'id_child' ],
'child_type' => $rel [ 'child_type' ],
'id_child_source_data' => $rel [ 'id_child_source_data' ],
'id_parent_agent' => $rel [ 'id_parent_agent' ],
'id_child_agent' => $rel [ 'id_child_agent' ],
2019-03-22 15:06:01 +01:00
'link_color' => $rel [ 'link_color' ],
2019-03-22 15:08:44 +01:00
'text_start' => $rel [ 'text_start' ],
'text_end' => $rel [ 'text_end' ],
2019-03-18 18:11:54 +01:00
];
2019-03-11 20:10:08 +01:00
2019-03-18 18:11:54 +01:00
$found = 0 ;
2019-03-20 13:10:20 +01:00
if ( isset ( $tmp [ 'id_parent_source_data' ])) {
// Avoid [child - parent] : [parent - child] relation duplicates.
if ( is_array ( $parents [ $tmp [ 'id_parent_source_data' ]])) {
foreach ( $parents [ $tmp [ 'id_parent_source_data' ]] as $k ) {
if ( $k === $tmp [ 'id_child_source_data' ]) {
$found = 1 ;
break ;
}
2019-03-19 20:43:08 +01:00
}
2019-03-20 13:10:20 +01:00
} else {
$parents [ $tmp [ 'id_parent_source_data' ]] = [];
2019-03-18 18:11:54 +01:00
}
}
if ( $found == 0 ) {
$parents [ $tmp [ 'id_child_source_data' ]][] = $tmp [ 'id_parent_source_data' ];
$graph [ 'relations' ][] = $tmp ;
}
2019-03-11 20:10:08 +01:00
}
2019-03-21 21:34:56 +01:00
// Prioritize relations between same nodes.
$this -> cleanGraphRelations ();
2019-03-19 20:43:08 +01:00
// Save data.
2019-03-20 13:10:20 +01:00
if ( $this -> idMap > 0 && ( isset ( $this -> map [ '__simulated' ]) === false )) {
2021-09-23 17:01:22 +02:00
$graph = save_generate_nodes ( $this -> idMap , $graph );
2019-03-11 20:10:08 +01:00
db_process_sql_update (
'tmap' ,
[
2019-03-21 20:52:01 +01:00
'width' => $this -> map [ 'width' ],
'height' => $this -> map [ 'height' ],
2019-03-12 12:05:54 +01:00
'center_x' => $this -> map [ 'center_x' ],
'center_y' => $this -> map [ 'center_y' ],
2019-03-11 20:10:08 +01:00
],
2019-03-12 12:05:54 +01:00
[ 'id' => $this -> idMap ]
2019-03-11 20:10:08 +01:00
);
} else {
2019-03-12 12:05:54 +01:00
$this -> map [ 'center_x' ] = $node_center [ 'x' ];
$this -> map [ 'center_y' ] = $node_center [ 'y' ];
2019-03-22 03:56:31 +01:00
if ( ! isset ( $this -> map [ 'center_x' ])
&& ! isset ( $this -> map [ 'center_y' ])
) {
$this -> map [ 'center_x' ] = ( $nodes [ 0 ][ 'x' ] - MAP_X_CORRECTION );
$this -> map [ 'center_y' ] = ( $nodes [ 0 ][ 'y' ] - MAP_Y_CORRECTION );
}
2019-03-11 20:10:08 +01:00
}
2019-03-17 01:39:56 +01:00
$this -> graph = $graph ;
2019-03-11 15:09:31 +01:00
}
/**
* Transform node information into JS data .
*
* @ return string HTML code with JS data .
*/
public function loadMapData ()
{
2019-10-11 13:51:52 +02:00
global $config ;
2019-03-11 15:09:31 +01:00
$networkmap = $this -> map ;
2019-10-11 13:51:52 +02:00
// ACL.
$networkmap_write = check_acl (
$config [ 'id_user' ],
$networkmap [ 'id_group' ],
'MW'
);
2019-03-12 12:05:54 +01:00
$simulate = false ;
2019-03-20 13:10:20 +01:00
if ( isset ( $networkmap [ '__simulated' ]) === false ) {
2020-03-26 12:29:38 +01:00
if ( $this -> widget ) {
$networkmap [ 'filter' ] = $this -> mapOptions ;
} else {
$networkmap [ 'filter' ] = json_decode (
$networkmap [ 'filter' ],
true
);
}
2019-03-12 16:22:28 +01:00
$networkmap [ 'filter' ][ 'holding_area' ] = [
500 ,
500 ,
];
$holding_area_title = __ ( 'Holding Area' );
2019-03-12 12:05:54 +01:00
} else {
$simulate = true ;
2019-03-12 16:22:28 +01:00
$holding_area_title = '' ;
$networkmap [ 'filter' ][ 'holding_area' ] = [
0 ,
0 ,
];
2019-03-11 20:10:08 +01:00
}
2019-03-19 20:43:08 +01:00
// Prioritize relations between same nodes.
$this -> cleanGraphRelations ();
2019-03-11 15:10:22 +01:00
2019-03-12 10:29:19 +01:00
// Print some params to handle it in js.
2020-02-06 14:32:43 +01:00
html_print_input_hidden ( 'widget' , $this -> widget );
2019-03-12 10:29:19 +01:00
html_print_input_hidden ( 'product_name' , get_product_name ());
html_print_input_hidden ( 'center_logo' , ui_get_full_url ( ui_get_logo_to_center_networkmap ()));
2019-03-11 15:09:31 +01:00
$output .= ' < script type = " text/javascript " >
////////////////////////////////////////////////////////////////////
// VARS FROM THE DB
////////////////////////////////////////////////////////////////////
var url_background_grid = " '.ui_get_full_url('images/background_grid.png').' " ;
2019-03-11 20:10:08 +01:00
' ;
2019-03-12 10:29:19 +01:00
$output .= 'var networkmap_id = "' . $this -> idMap . " \" ; \n " ;
2019-03-11 20:10:08 +01:00
2019-03-11 16:57:54 +01:00
if ( ! empty ( $networkmap [ 'filter' ])) {
if ( empty ( $networkmap [ 'filter' ][ 'x_offs' ])) {
$output .= " var x_offs =null; \n " ;
} else {
$output .= 'var x_offs =' . $networkmap [ 'filter' ][ 'x_offs' ] . " ; \n " ;
}
if ( empty ( $networkmap [ 'filter' ][ 'y_offs' ])) {
$output .= " var y_offs =null; \n " ;
} else {
$output .= 'var y_offs =' . $networkmap [ 'filter' ][ 'y_offs' ] . " ; \n " ;
}
2019-03-11 15:09:31 +01:00
2019-03-22 03:56:31 +01:00
if ( empty ( $networkmap [ 'filter' ][ 'z_dash' ])) {
2019-03-11 20:10:08 +01:00
$output .= " var z_dash =null; \n " ;
} else {
$output .= 'var z_dash = ' . $networkmap [ 'filter' ][ 'z_dash' ] . " ; \n " ;
}
2019-03-11 15:09:31 +01:00
} else {
$output .= " var x_offs = null; \n " ;
$output .= " var y_offs = null; \n " ;
$output .= " var z_dash = null; \n " ;
}
2019-04-22 09:33:51 +02:00
if ( empty ( $networkmap [ 'filter' ][ 'node_radius' ]) === true ) {
$networkmap [ 'filter' ][ 'node_radius' ] = $this -> mapOptions [ 'map_filter' ][ 'node_radius' ];
}
2019-03-11 15:09:31 +01:00
$output .= 'var networkmap_refresh_time = 1000 * ' . $networkmap [ 'source_period' ] . " ; \n " ;
$output .= 'var networkmap_center = [ ' . $networkmap [ 'center_x' ] . ', ' . $networkmap [ 'center_y' ] . " ]; \n " ;
$output .= 'var networkmap_dimensions = [ ' . $networkmap [ 'width' ] . ', ' . $networkmap [ 'height' ] . " ]; \n " ;
2019-10-11 13:51:52 +02:00
$output .= 'var networkmap_write = ' . $networkmap_write . " ; \n " ;
2019-03-11 15:09:31 +01:00
$output .= 'var node_radius = ' . $networkmap [ 'filter' ][ 'node_radius' ] . " ; \n " ;
$output .= 'var networkmap_holding_area_dimensions = ' . json_encode ( $networkmap [ 'filter' ][ 'holding_area' ]) . " ; \n " ;
$output .= " var networkmap = { 'nodes': [], 'links': []}; \n " ;
2019-03-19 20:43:08 +01:00
// Init.
2019-03-11 15:09:31 +01:00
$count_item_holding_area = 0 ;
$count = 0 ;
2019-03-19 20:43:08 +01:00
// Translate nodes to JS Nodes.
$nodes = $this -> graph [ 'nodes' ];
if ( is_array ( $nodes ) === false ) {
$nodes = [];
2019-03-11 15:09:31 +01:00
}
2019-03-29 20:52:51 +01:00
$this -> nodesJS = $this -> nodesToJS ( $nodes );
2019-04-05 16:43:36 +02:00
2019-03-29 20:52:51 +01:00
$output .= 'networkmap.nodes = (' . json_encode ( $this -> nodesJS ) . " ); \n " ;
// Clean.
unset ( $this -> nodes );
unset ( $this -> rawNodes );
unset ( $this -> nodeMapping );
2019-03-11 15:09:31 +01:00
2019-03-19 20:43:08 +01:00
// Translate edges to js links.
$relations = $this -> graph [ 'relations' ];
if ( is_array ( $relations ) === false ) {
2019-03-11 15:09:31 +01:00
$relations = [];
}
2019-03-29 20:52:51 +01:00
$this -> relationsJS = $this -> edgeToJS ( $relations );
$output .= 'networkmap.links = (' . json_encode ( $this -> relationsJS ) . " ); \n " ;
// Clean.
unset ( $this -> relations );
2019-03-11 15:09:31 +01:00
$output .= '
////////////////////////////////////////////////////////////////////
// INTERFACE STATUS COLORS
////////////////////////////////////////////////////////////////////
' ;
$module_color_status = [];
$module_color_status [] = [
'status_code' => AGENT_MODULE_STATUS_NORMAL ,
'color' => COL_NORMAL ,
];
$module_color_status [] = [
'status_code' => AGENT_MODULE_STATUS_CRITICAL_BAD ,
'color' => COL_CRITICAL ,
];
$module_color_status [] = [
'status_code' => AGENT_MODULE_STATUS_WARNING ,
'color' => COL_WARNING ,
];
$module_color_status [] = [
'status_code' => AGENT_STATUS_ALERT_FIRED ,
'color' => COL_ALERTFIRED ,
];
$module_color_status_unknown = COL_UNKNOWN ;
$output .= 'var module_color_status = ' . json_encode ( $module_color_status ) . " ; \n " ;
$output .= " var module_color_status_unknown = ' " . $module_color_status_unknown . " '; \n " ;
$output .= '
////////////////////////////////////////////////////////////////////
// Other vars
////////////////////////////////////////////////////////////////////
' ;
$output .= " var translation_none = ' " . __ ( 'None' ) . " '; \n " ;
$output .= " var dialog_node_edit_title = ' " . __ ( 'Edit node %s' ) . " '; \n " ;
2019-03-12 16:22:28 +01:00
$output .= " var holding_area_title = ' " . $holding_area_title . " '; \n " ;
2019-03-11 15:09:31 +01:00
$output .= " var edit_menu = ' " . __ ( 'Show details and options' ) . " '; \n " ;
$output .= " var interface_link_add = ' " . __ ( 'Add a interface link' ) . " '; \n " ;
$output .= " var set_parent_link = ' " . __ ( 'Set parent interface' ) . " '; \n " ;
$output .= " var set_as_children_menu = ' " . __ ( 'Set as children' ) . " '; \n " ;
$output .= " var set_parent_menu = ' " . __ ( 'Set parent' ) . " '; \n " ;
$output .= " var abort_relationship_menu = ' " . __ ( 'Abort the action of set relationship' ) . " '; \n " ;
$output .= " var delete_menu = ' " . __ ( 'Delete' ) . " '; \n " ;
$output .= " var add_node_menu = ' " . __ ( 'Add node' ) . " '; \n " ;
$output .= " var set_center_menu = ' " . __ ( 'Set center' ) . " '; \n " ;
$output .= " var refresh_menu = ' " . __ ( 'Refresh' ) . " '; \n " ;
$output .= " var refresh_holding_area_menu = ' " . __ ( 'Refresh Holding area' ) . " '; \n " ;
$output .= " var ok_button = ' " . __ ( 'Proceed' ) . " '; \n " ;
$output .= " var message_to_confirm = ' " . __ ( 'Resetting the map will delete all customizations you have done, including manual relationships between elements, new items, etc.' ) . " '; \n " ;
$output .= " var warning_message = ' " . __ ( 'WARNING' ) . " '; \n " ;
$output .= " var ok_button = ' " . __ ( 'Proceed' ) . " '; \n " ;
$output .= " var cancel_button = ' " . __ ( 'Cancel' ) . " '; \n " ;
$output .= " var restart_map_menu = ' " . __ ( 'Restart map' ) . " '; \n " ;
$output .= " var abort_relationship_interface = ' " . __ ( 'Abort the interface relationship' ) . " '; \n " ;
$output .= " var abort_relationship_menu = ' " . __ ( 'Abort the action of set relationship' ) . " '; \n " ;
$output .= '</script>' ;
return $output ;
}
2019-03-21 16:16:53 +01:00
/**
* Generates a simple interface to interact with nodes .
*
* @ return string HTML code for simple interface .
*/
public function loadSimpleInterface ()
{
2021-04-22 13:23:49 +02:00
$output = '' ;
2021-03-11 15:40:23 +01:00
$output .= '<div id="dialog_node_edit" class="invisible" title="' ;
2019-03-21 16:16:53 +01:00
$output .= __ ( 'Edit node' ) . '">' ;
2021-03-11 15:40:23 +01:00
$output .= '<div class="left w100p">' ;
2019-03-21 16:16:53 +01:00
$table = new StdClass ();
$table -> id = 'node_details' ;
$table -> width = '100%' ;
$table -> data = [];
$table -> data [ 0 ][ 0 ] = '<strong>' . __ ( 'Agent' ) . '</strong>' ;
$table -> data [ 0 ][ 1 ] = '' ;
$table -> data [ 1 ][ 0 ] = '<strong>' . __ ( 'Adresses' ) . '</strong>' ;
$table -> data [ 1 ][ 1 ] = '' ;
$table -> data [ 2 ][ 0 ] = '<strong>' . __ ( 'OS type' ) . '</strong>' ;
$table -> data [ 2 ][ 1 ] = '' ;
$table -> data [ 3 ][ 0 ] = '<strong>' . __ ( 'Group' ) . '</strong>' ;
$table -> data [ 3 ][ 1 ] = '' ;
$output .= ui_toggle (
html_print_table ( $table , true ),
__ ( 'Node Details' ),
__ ( 'Node Details' ),
2019-06-04 13:57:55 +02:00
'' ,
2019-03-21 16:16:53 +01:00
false ,
2019-06-11 12:58:18 +02:00
true
2019-03-21 16:16:53 +01:00
);
2019-03-25 11:02:16 +01:00
$output .= '</div>' ;
$output .= '</div>' ;
2019-03-21 16:16:53 +01:00
return $output ;
}
2019-03-11 15:09:31 +01:00
/**
* Show an advanced interface to manage dialogs .
*
* @ return string HTML code with dialogs .
*/
2019-03-11 15:37:08 +01:00
public function loadAdvancedInterface ()
2019-03-11 15:09:31 +01:00
{
$list_networkmaps = get_networkmaps ( $this -> idMap );
2021-09-23 17:19:47 +02:00
2021-09-23 17:01:22 +02:00
if ( empty ( $list_networkmaps ) === true ) {
2019-03-11 15:09:31 +01:00
$list_networkmaps = [];
}
2020-12-02 10:10:34 +01:00
$id = 'dialog_node_edit' ;
2019-03-11 15:09:31 +01:00
2021-09-23 17:01:22 +02:00
$output = '<div id="' . $id . '" class="invisible" title="' ;
2019-03-11 15:09:31 +01:00
$output .= __ ( 'Edit node' ) . '">' ;
2021-03-11 15:40:23 +01:00
$output .= '<div class="left w100p">' ;
2019-03-11 15:09:31 +01:00
2019-03-11 15:37:08 +01:00
$table = new StdClass ();
2019-03-11 15:09:31 +01:00
$table -> id = 'node_details' ;
$table -> width = '100%' ;
$table -> data = [];
$table -> data [ 0 ][ 0 ] = '<strong>' . __ ( 'Agent' ) . '</strong>' ;
$table -> data [ 0 ][ 1 ] = '' ;
$table -> data [ 1 ][ 0 ] = '<strong>' . __ ( 'Adresses' ) . '</strong>' ;
$table -> data [ 1 ][ 1 ] = '' ;
$table -> data [ 2 ][ 0 ] = '<strong>' . __ ( 'OS type' ) . '</strong>' ;
$table -> data [ 2 ][ 1 ] = '' ;
$table -> data [ 3 ][ 0 ] = '<strong>' . __ ( 'Group' ) . '</strong>' ;
$table -> data [ 3 ][ 1 ] = '' ;
$output .= ui_toggle (
html_print_table ( $table , true ),
__ ( 'Node Details' ),
__ ( 'Node Details' ),
2019-06-04 13:57:55 +02:00
'' ,
2019-03-11 15:09:31 +01:00
false ,
true
);
2019-03-11 15:37:08 +01:00
$table = new StdClass ();
2019-03-11 15:09:31 +01:00
$table -> id = 'interface_information' ;
$table -> width = '100%' ;
$table -> head [ 'interface_name' ] = __ ( 'Name' );
$table -> head [ 'interface_status' ] = __ ( 'Status' );
$table -> head [ 'interface_graph' ] = __ ( 'Graph' );
$table -> head [ 'interface_ip' ] = __ ( 'Ip' );
$table -> head [ 'interface_mac' ] = __ ( 'MAC' );
$table -> data = [];
$table -> rowstyle [ 'template_row' ] = 'display: none;' ;
$table -> data [ 'template_row' ][ 'interface_name' ] = '' ;
$table -> data [ 'template_row' ][ 'interface_status' ] = '' ;
$table -> data [ 'template_row' ][ 'interface_graph' ] = '' ;
$table -> data [ 'template_row' ][ 'interface_ip' ] = '' ;
$table -> data [ 'template_row' ][ 'interface_mac' ] = '' ;
$output .= ui_toggle (
html_print_table ( $table , true ),
__ ( 'Interface Information (SNMP)' ),
__ ( 'Interface Information (SNMP)' ),
2019-06-04 13:57:55 +02:00
'' ,
2019-03-11 15:09:31 +01:00
true ,
true
);
2019-03-11 15:37:08 +01:00
$table = new StdClass ();
2019-03-11 15:09:31 +01:00
$table -> id = 'node_options' ;
$table -> width = '100%' ;
$table -> data = [];
$table -> data [ 0 ][ 0 ] = __ ( 'Shape' );
$table -> data [ 0 ][ 1 ] = html_print_select (
[
'circle' => __ ( 'Circle' ),
'square' => __ ( 'Square' ),
'rhombus' => __ ( 'Rhombus' ),
],
'shape' ,
'' ,
'javascript:' ,
'' ,
0 ,
true
2021-03-11 15:40:23 +01:00
) . ' <span id="shape_icon_in_progress" class="invisible">' . html_print_image ( 'images/spinner.gif' , true ) . '</span><span id="shape_icon_correct" class="invisible">' . html_print_image ( 'images/success.png' , true , [ 'width' => '18px' ]) . '</span><span id="shape_icon_fail" class="invisible">' . html_print_image ( 'images/icono-bad.png' , true , [ 'width' => '18px' ]) . '</span>' ;
2019-03-11 15:09:31 +01:00
$table -> data [ 'node_name' ][ 0 ] = __ ( 'Name' );
$table -> data [ 'node_name' ][ 1 ] = html_print_input_text (
'edit_name_node' ,
'' ,
__ ( 'name node' ),
'20' ,
'50' ,
true
);
$table -> data [ 'node_name' ][ 2 ] = html_print_button (
__ ( 'Update node' ),
'' ,
false ,
'' ,
2021-06-04 13:03:35 +02:00
'class="sub next"' ,
2019-03-11 15:09:31 +01:00
true
);
$table -> data [ 'fictional_node_name' ][ 0 ] = __ ( 'Name' );
$table -> data [ 'fictional_node_name' ][ 1 ] = html_print_input_text (
'edit_name_fictional_node' ,
'' ,
__ ( 'name fictional node' ),
'20' ,
'50' ,
true
);
$table -> data [ 'fictional_node_networkmap_link' ][ 0 ] = __ ( 'Networkmap to link' );
$table -> data [ 'fictional_node_networkmap_link' ][ 1 ] = html_print_select (
$list_networkmaps ,
'edit_networkmap_to_link' ,
'' ,
'' ,
'' ,
0 ,
true
);
$table -> data [ 'fictional_node_update_button' ][ 0 ] = '' ;
$table -> data [ 'fictional_node_update_button' ][ 1 ] = html_print_button (
__ ( 'Update fictional node' ),
'' ,
false ,
'add_fictional_node();' ,
2021-06-04 13:03:35 +02:00
'class="sub next"' ,
2019-03-11 15:09:31 +01:00
true
);
2021-09-23 17:01:22 +02:00
$output .= ui_toggle (
html_print_table ( $table , true ),
__ ( 'Node options' ),
__ ( 'Node options' ),
'' ,
true ,
true
);
2019-03-11 15:09:31 +01:00
2019-03-11 15:37:08 +01:00
$table = new StdClass ();
2019-03-11 15:09:31 +01:00
$table -> id = 'relations_table' ;
$table -> width = '100%' ;
$table -> head = [];
$table -> head [ 'node_source' ] = __ ( 'Node source' );
$table -> head [ 'interface_source' ] = __ ( 'Interface source' );
$table -> head [ 'interface_target' ] = __ ( 'Interface Target' );
$table -> head [ 'node_target' ] = __ ( 'Node target' );
$table -> head [ 'edit' ] = '<span title="' . __ ( 'Edit' ) . '">' . __ ( 'E.' ) . '</span>' ;
$table -> data = [];
$table -> rowstyle [ 'template_row' ] = 'display: none;' ;
$table -> data [ 'template_row' ][ 'node_source' ] = '' ;
2021-08-24 11:52:37 +02:00
// Inputs must be not select2, cause duplication make issues.
2019-03-11 15:09:31 +01:00
$table -> data [ 'template_row' ][ 'interface_source' ] = html_print_select (
[],
'interface_source' ,
'' ,
'' ,
__ ( 'None' ),
0 ,
2021-08-24 11:52:37 +02:00
true ,
false ,
true ,
'' ,
false ,
false ,
false ,
false ,
false ,
'' ,
false ,
false ,
false ,
false ,
false
2019-03-11 15:09:31 +01:00
);
$table -> data [ 'template_row' ][ 'interface_target' ] = html_print_select (
[],
'interface_target' ,
'' ,
'' ,
__ ( 'None' ),
0 ,
2021-08-24 11:52:37 +02:00
true ,
false ,
true ,
'' ,
false ,
false ,
false ,
false ,
false ,
'' ,
false ,
false ,
false ,
false ,
false
2019-03-11 15:09:31 +01:00
);
$table -> data [ 'template_row' ][ 'node_target' ] = '' ;
$table -> data [ 'template_row' ][ 'edit' ] = '' ;
2021-06-04 13:03:35 +02:00
$table -> data [ 'template_row' ][ 'edit' ] .= '<span class="edit_icon_correct" style="display: none">' . html_print_image ( 'images/dot_green.png' , true ) . '</span><span class="edit_icon_fail" style="display: none" >' . html_print_image ( 'images/dot_red.png' , true ) . '</span><span class="edit_icon_progress" style="display: none">' . html_print_image ( 'images/spinner.gif' , true ) . '</span><span class="edit_icon"><a class="edit_icon_link" title="' . __ ( 'Update' ) . '" href="#">' . html_print_image ( 'images/config.png' , true , [ 'class' => 'invert_filter' ]) . '</a></span>' ;
2019-03-11 15:09:31 +01:00
2021-06-04 13:03:35 +02:00
$table -> data [ 'template_row' ][ 'edit' ] .= '<a class="delete_icon" href="#">' . html_print_image ( 'images/delete.png' , true , [ 'class' => 'invert_filter' ]) . '</a>' ;
2019-03-11 15:09:31 +01:00
$table -> colspan [ 'no_relations' ][ '0' ] = 5 ;
$table -> cellstyle [ 'no_relations' ][ '0' ] = 'text-align: center;' ;
$table -> data [ 'no_relations' ][ '0' ] = __ ( 'There are not relations' );
$table -> colspan [ 'loading' ][ '0' ] = 5 ;
$table -> cellstyle [ 'loading' ][ '0' ] = 'text-align: center;' ;
$table -> data [ 'loading' ][ '0' ] = html_print_image (
'images/wait.gif' ,
true
);
2021-09-23 17:01:22 +02:00
$output .= ui_toggle (
html_print_table ( $table , true ),
__ ( 'Relations' ),
__ ( 'Relations' ),
'' ,
true ,
true
);
2019-03-11 15:09:31 +01:00
$output .= '</div></div>' ;
2021-03-11 15:40:23 +01:00
$output .= '<div id="dialog_interface_link" class="invisible" title="Interface link">' ;
$output .= '<div class="left w100p">' ;
2019-03-11 15:09:31 +01:00
$table = new stdClass ();
$table -> id = 'interface_link_table' ;
$table -> width = '100%' ;
$table -> head [ 'node_source_interface' ] = __ ( 'Node source' );
$table -> head [ 'interface_source_select' ] = __ ( 'Interface source' );
$table -> head [ 'interface_target_select' ] = __ ( 'Interface Target' );
$table -> head [ 'node_target_interface' ] = __ ( 'Node target' );
$table -> data = [];
2019-03-25 15:52:15 +01:00
$table -> data [ 'interface_row' ][ 'node_source_interface' ] = html_print_label (
'' ,
'node_source_interface' ,
true
);
2019-03-11 15:09:31 +01:00
$table -> data [ 'interface_row' ][ 'interface_source_select' ] = html_print_select (
[],
'interface_source_select' ,
'' ,
'' ,
__ ( 'None' ),
0 ,
true
);
$table -> data [ 'interface_row' ][ 'interface_target_select' ] = html_print_select (
[],
'interface_target_select' ,
'' ,
'' ,
__ ( 'None' ),
0 ,
true
);
$table -> data [ 'interface_row' ][ 'node_target_interface' ] = html_print_label (
'' ,
2019-03-25 15:52:15 +01:00
'node_target_interface' ,
true
2019-03-11 15:09:31 +01:00
);
2019-03-25 15:52:15 +01:00
$output .= '<br>' ;
2019-03-11 15:09:31 +01:00
$table -> data [ 'interface_row' ][ 'interface_link_button' ] = html_print_button (
__ ( 'Add interface link' ),
'' ,
false ,
'add_interface_link_js();' ,
'class="sub"' ,
true
);
$output .= html_print_table ( $table , true );
$output .= '</div></div>' ;
2021-03-11 15:40:23 +01:00
$output .= '<div id="dialog_node_add" class="invisible" title="' ;
2019-03-11 15:09:31 +01:00
$output .= __ ( 'Add node' ) . '">' ;
2021-03-11 15:40:23 +01:00
$output .= '<div class="left w100p">' ;
2019-03-11 15:09:31 +01:00
2019-03-11 15:37:08 +01:00
$table = new StdClass ();
2019-03-11 15:09:31 +01:00
$table -> width = '100%' ;
$table -> data = [];
$table -> data [ 0 ][ 0 ] = __ ( 'Agent' );
$params = [];
$params [ 'return' ] = true ;
$params [ 'show_helptip' ] = true ;
$params [ 'input_name' ] = 'agent_name' ;
$params [ 'input_id' ] = 'agent_name' ;
$params [ 'print_hidden_input_idagent' ] = true ;
$params [ 'hidden_input_idagent_name' ] = 'id_agent' ;
$params [ 'disabled_javascript_on_blur_function' ] = true ;
$table -> data [ 0 ][ 1 ] = ui_print_agent_autocomplete_input ( $params );
$table -> data [ 1 ][ 0 ] = '' ;
$table -> data [ 1 ][ 1 ] = html_print_button (
__ ( 'Add agent node' ),
'' ,
false ,
'add_agent_node();' ,
'class="sub"' ,
true
) . html_print_image (
'images/error_red.png' ,
true ,
[
'id' => 'error_red' ,
'style' => 'vertical-align: bottom;display: none;' ,
'class' => 'forced_title' ,
2019-03-12 19:23:40 +01:00
'alt' => '' ,
2019-03-11 15:09:31 +01:00
'data-title' => 'data-use_title_for_force_title:1' ,
],
false
);
$add_agent_node_html = html_print_table ( $table , true );
$output .= ui_toggle (
$add_agent_node_html ,
__ ( 'Add agent node' ),
__ ( 'Add agent node' ),
2019-06-04 13:57:55 +02:00
'' ,
2019-03-11 15:09:31 +01:00
false ,
true
);
2019-03-11 15:37:08 +01:00
$table = new StdClass ();
2019-03-11 15:09:31 +01:00
$table -> width = '100%' ;
$table -> data = [];
$table -> data [ 0 ][ 0 ] = __ ( 'Group' );
$table -> data [ 0 ][ 1 ] = html_print_select_groups (
false ,
2021-05-13 13:33:45 +02:00
'AR' ,
2019-03-11 15:09:31 +01:00
false ,
'group_for_show_agents' ,
- 1 ,
'choose_group_for_show_agents()' ,
__ ( 'None' ),
- 1 ,
true
);
2021-07-14 18:00:07 +02:00
$table -> data [ 0 ][ 2 ] = html_print_checkbox (
'group_recursion' ,
0 ,
false ,
true ,
false ,
'choose_group_for_show_agents()'
) . __ ( 'Recursion' );
2019-03-11 15:09:31 +01:00
$table -> data [ 1 ][ 0 ] = __ ( 'Agents' );
$table -> data [ 1 ][ 1 ] = html_print_select (
[ - 1 => __ ( 'None' )],
'agents_filter_group' ,
- 1 ,
'' ,
'' ,
0 ,
true ,
true ,
true ,
'' ,
false ,
'width: 170px;' ,
false ,
5
);
$table -> data [ 2 ][ 0 ] = '' ;
$table -> data [ 2 ][ 1 ] = html_print_button (
__ ( 'Add agent node' ),
'' ,
false ,
'add_agent_node_from_the_filter_group();' ,
'class="sub"' ,
true
);
$add_agent_node_html = html_print_table ( $table , true );
$output .= ui_toggle (
$add_agent_node_html ,
__ ( 'Add agent node (filter by group)' ),
__ ( 'Add agent node' ),
2019-06-04 13:57:55 +02:00
'' ,
2019-03-11 15:09:31 +01:00
true ,
true
);
2019-03-11 15:37:08 +01:00
$table = new StdClass ();
2019-03-11 15:09:31 +01:00
$table -> width = '100%' ;
$table -> data = [];
$table -> data [ 0 ][ 0 ] = __ ( 'Name' );
$table -> data [ 0 ][ 1 ] = html_print_input_text (
'name_fictional_node' ,
'' ,
__ ( 'name fictional node' ),
'20' ,
'50' ,
true
);
$table -> data [ 1 ][ 0 ] = __ ( 'Networkmap to link' );
$table -> data [ 1 ][ 1 ] = html_print_select (
$list_networkmaps ,
'networkmap_to_link' ,
'' ,
'' ,
'' ,
0 ,
true
);
$table -> data [ 2 ][ 0 ] = '' ;
$table -> data [ 2 ][ 1 ] = html_print_button (
__ ( 'Add fictional node' ),
'' ,
false ,
'add_fictional_node();' ,
'class="sub"' ,
true
);
$add_agent_node_html = html_print_table ( $table , true );
$output .= ui_toggle (
$add_agent_node_html ,
__ ( 'Add fictional point' ),
__ ( 'Add agent node' ),
2019-06-04 13:57:55 +02:00
'' ,
2019-03-11 15:09:31 +01:00
true ,
true
);
$output .= '</div></div>' ;
return $output ;
}
/**
* Loads advanced map controller ( JS ) .
*
2020-05-21 19:28:24 +02:00
* @ param boolean $return Dumps to output if false .
*
2019-03-11 15:09:31 +01:00
* @ return string HTML code for advanced controller .
*/
2020-05-21 19:28:24 +02:00
public function loadController ( ? bool $return = true )
2019-03-11 15:09:31 +01:00
{
$output = '' ;
2021-09-23 17:01:22 +02:00
if ( $this -> useTooltipster
2019-03-22 03:56:31 +01:00
) {
$output .= ' < script type = " text/javascript " >
$ ( function () {
2019-03-29 20:31:55 +01:00
controller = new SimpleMapController ({
map_width : '.$this->map[' width '].' ,
map_height : '.$this->map[' height '].' ,
id : " '. $this->idMap .' " ,
target : " #simple_map " ,
2019-03-29 20:52:51 +01:00
nodes : '.json_encode($this->nodesJS).' ,
arrows : '.json_encode($this->relationsJS).' ,
2019-03-29 20:31:55 +01:00
center_x : '.$this->map[' center_x '].' ,
center_y : '.$this->map[' center_y '].' ,
z_dash : '.$this->map[' filter '][' z_dash '].' ,
font_size : '.$this->mapOptions[' font_size '].' ,
homedir : " '.ui_get_full_url(false).' " ,
custom_params : '.json_encode($this->tooltipParams).'
});
2019-03-22 03:56:31 +01:00
controller . init_map ();
});
</ script > ' ;
} else {
// Generate JS for advanced controller.
$output .= '
2019-03-11 15:09:31 +01:00
< script type = " text/javascript " >
////////////////////////////////////////////////////////////////////////
// document ready
////////////////////////////////////////////////////////////////////////
$ ( document ) . ready ( function () {
init_graph ({
graph : networkmap ,
networkmap_center : networkmap_center ,
networkmap_dimensions : networkmap_dimensions ,
2021-09-23 17:01:22 +02:00
enterprise_installed : 1 ,
2019-03-11 15:09:31 +01:00
node_radius : node_radius ,
holding_area_dimensions : networkmap_holding_area_dimensions ,
2019-03-26 16:46:32 +01:00
url_background_grid : url_background_grid ,
2020-09-24 16:20:13 +02:00
font_size : '.$this->mapOptions[' font_size '].' ,
base_url_homedir : " '.ui_get_full_url(false).' "
2019-03-11 15:09:31 +01:00
});
init_drag_and_drop ();
init_minimap ();
function_open_minimap ();
$ ( document . body ) . on ( " mouseleave " ,
" .context-menu-list " ,
function ( e ) {
try {
$ ( " #networkconsole_'. $this->idMap .' " ) . contextMenu ( " hide " );
}
catch ( err ) {
}
}
);
});
</ script > ' ;
2019-03-22 03:56:31 +01:00
}
2019-03-11 15:09:31 +01:00
if ( $return === false ) {
echo $output ;
}
return $output ;
}
/**
* Load networkmap HTML skel and JS requires .
*
* @ return string HTML code for skel .
*/
public function loadMapSkel ()
{
global $config ;
2021-09-23 17:01:22 +02:00
if ( isset ( $this -> useTooltipster ) === true
&& ( bool ) $this -> useTooltipster === true
2019-03-22 03:56:31 +01:00
) {
2021-04-06 16:47:32 +02:00
$output = '<script type="text/javascript" src="' . ui_get_full_url (
2019-03-22 03:56:31 +01:00
'include/javascript/d3.3.5.14.js'
) . '" charset="utf-8"></script>' ;
$output .= '<script type="text/javascript" src="' . ui_get_full_url (
2021-09-23 17:01:22 +02:00
'include/javascript/SimpleMapController.js'
2019-03-22 03:56:31 +01:00
) . '"></script>' ;
$output .= '<script type="text/javascript" src="' . ui_get_full_url (
2021-09-23 17:01:22 +02:00
'include/javascript/tooltipster.bundle.min.js'
2019-03-22 03:56:31 +01:00
) . '"></script>' ;
$output .= '<script type="text/javascript" src="' . ui_get_full_url (
'include/javascript/jquery.svg.js'
) . '"></script>' ;
$output .= '<script type="text/javascript" src="' . ui_get_full_url (
'include/javascript/jquery.svgdom.js'
) . '"></script>' ;
$output .= '<link rel="stylesheet" type="text/css" href="' . ui_get_full_url (
2021-09-23 17:01:22 +02:00
'include/styles/tooltipster.bundle.min.css'
2019-03-22 03:56:31 +01:00
) . '" />' . " \n " ;
2021-11-29 15:54:45 +01:00
ui_require_css_file ( 'jquery.contextMenu' , 'include/styles/js/' );
$output .= '<script type="text/javascript" src="' ;
$output .= ui_get_full_url (
'include/javascript/jquery.contextMenu.js' ,
false ,
false ,
false
);
$output .= '" charset="utf-8"></script>' ;
2019-03-22 03:56:31 +01:00
2019-03-25 11:02:16 +01:00
$output .= '<div id="simple_map" data-id="' . $this -> idMap . '" ' ;
2021-08-31 11:05:41 +02:00
$output .= 'class="border_1px_dd" style="' ;
2019-03-29 20:31:55 +01:00
if ( $this -> fullSize ) {
$output .= ' width:100%' ;
$output .= ' ;height: 100%">' ;
$output .= '<svg id="svg' . $this -> idMap . '" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" pointer-events="all" width="100%" height="100%">' ;
} else {
$output .= ' width:' . $this -> mapOptions [ 'width' ] . 'px' ;
$output .= ' ;height:' . $this -> mapOptions [ 'height' ] . 'px">' ;
$output .= '<svg id="svg' . $this -> idMap . '" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" pointer-events="all" width="' . $this -> mapOptions [ 'width' ] . '" height="' . $this -> mapOptions [ 'height' ] . 'px">' ;
}
2019-03-22 03:56:31 +01:00
$output .= '</svg>' ;
$output .= '</div>' ;
} else {
// Load default interface.
ui_require_css_file ( 'networkmap' );
ui_require_css_file ( 'jquery.contextMenu' , 'include/styles/js/' );
$output = '' ;
$minimap_display = '' ;
if ( $this -> mapOptions [ 'pure' ]) {
$minimap_display = 'none' ;
}
2019-03-11 15:09:31 +01:00
2019-03-22 03:56:31 +01:00
$networkmap = $this -> map ;
if ( is_array ( $networkmap [ 'filter' ]) === false ) {
$networkmap [ 'filter' ] = json_decode ( $networkmap [ 'filter' ], true );
}
2019-03-11 15:09:31 +01:00
2019-03-22 03:56:31 +01:00
$networkmap [ 'filter' ][ 'l2_network_interfaces' ] = 1 ;
2019-03-11 15:09:31 +01:00
2021-04-06 16:47:32 +02:00
$output .= '<script type="text/javascript" src="' ;
$output .= ui_get_full_url (
'include/javascript/d3.3.5.14.js' ,
false ,
false ,
false
);
$output .= '" charset="utf-8"></script>' ;
2019-03-22 03:56:31 +01:00
if ( isset ( $this -> map [ '__simulated' ]) === false ) {
// Load context menu if manageable networkmap.
2021-04-06 16:47:32 +02:00
$output .= '<script type="text/javascript" src="' ;
$output .= ui_get_full_url (
'include/javascript/jquery.contextMenu.js' ,
false ,
false ,
false
);
$output .= '" charset="utf-8"></script>' ;
2019-03-22 03:56:31 +01:00
}
2019-03-11 15:09:31 +01:00
2021-04-06 16:47:32 +02:00
$output .= '<script type="text/javascript" src="' ;
$output .= ui_get_full_url (
'include/javascript/functions_pandora_networkmap.js' ,
false ,
false ,
false
);
$output .= '" charset="utf-8"></script>' ;
2019-03-11 15:09:31 +01:00
2019-03-22 03:56:31 +01:00
// Open networkconsole_id div.
$output .= '<div id="networkconsole_' . $networkmap [ 'id' ] . '"' ;
2019-03-27 18:31:02 +01:00
if ( $this -> fullSize ) {
2020-03-26 12:29:38 +01:00
if ( $this -> widget ) {
2021-03-11 15:40:23 +01:00
$output .= ' class="networkconsole">' ;
2020-03-26 12:29:38 +01:00
} else {
2021-03-11 15:40:23 +01:00
$output .= ' class="networkconsole">' ;
2020-03-26 12:29:38 +01:00
}
2019-03-27 11:47:09 +01:00
} else {
$output .= ' style="width: ' . $this -> mapOptions [ 'width' ] . 'px; height: ' . $this -> mapOptions [ 'height' ] . 'px;position: relative; overflow: hidden; background: #FAFAFA">' ;
}
2019-03-11 15:09:31 +01:00
2019-03-22 03:56:31 +01:00
$output .= '<div style="display: ' . $minimap_display . ';">' ;
$output .= '<canvas id="minimap_' . $networkmap [ 'id' ] . '"' ;
2021-03-11 15:40:23 +01:00
$output .= ' class="minimap">' ;
2019-03-22 03:56:31 +01:00
$output .= '</canvas>' ;
$output .= '<div id="arrow_minimap_' . $networkmap [ 'id' ] . '"' ;
2021-03-11 15:40:23 +01:00
$output .= ' class="absolute left_0px top_0px">' ;
2019-03-22 03:56:31 +01:00
$output .= '<a title="' . __ ( 'Open Minimap' ) . '" href="javascript: toggle_minimap();">' ;
2019-05-16 17:13:14 +02:00
$output .= html_print_image ( '/images/minimap_open_arrow.png' , true , [ 'id' => 'arrow_minimap_' . $networkmap [ 'id' ]]);
2020-05-20 19:04:42 +02:00
$output .= '</a></div></div>' ;
2019-03-11 15:09:31 +01:00
2019-03-22 03:56:31 +01:00
$output .= '<div id="hide_labels_' . $networkmap [ 'id' ] . '"' ;
2021-03-11 15:40:23 +01:00
$output .= ' class="absolute right_10px top_10px">' ;
2019-03-22 03:56:31 +01:00
$output .= '<a title="' . __ ( 'Hide Labels' ) . '" href="javascript: hide_labels();">' ;
2019-05-16 17:13:14 +02:00
$output .= html_print_image ( '/images/icono_borrar.png' , true , [ 'id' => 'image_hide_show_labels' ]);
2019-03-22 03:56:31 +01:00
$output .= '</a></div>' ;
2019-03-11 15:09:31 +01:00
2019-03-22 03:56:31 +01:00
$output .= '<div id="holding_spinner_' . $networkmap [ 'id' ] . '" ' ;
2021-03-11 15:40:23 +01:00
$output .= ' class="holding_networkmap">' ;
2019-05-16 17:13:14 +02:00
$output .= html_print_image ( '/images/spinner.png' , true , [ 'id' => 'image_hide_show_labels' ]);
2019-03-22 03:56:31 +01:00
$output .= '</div>' ;
2019-03-11 15:09:31 +01:00
2019-03-22 03:56:31 +01:00
// Close networkconsole_id div.
$output .= " </div> \n " ;
}
2019-03-11 15:09:31 +01:00
return $output ;
}
2019-03-07 18:57:48 +01:00
/**
* Print all components required to visualizate a network map .
*
* @ param boolean $return Return as string or not .
*
* @ return string HTML code .
*/
2021-01-15 13:52:31 +01:00
public function printMap ( $return = false , $ignore_acl = false )
2019-03-07 18:57:48 +01:00
{
global $config ;
2020-05-21 19:28:24 +02:00
$networkmap = $this -> map ;
2021-01-15 13:52:31 +01:00
if ( $ignore_acl === false ) {
// ACL.
$networkmap_read = check_acl (
$config [ 'id_user' ],
$networkmap [ 'id_group' ],
'MR'
2019-03-07 18:57:48 +01:00
);
2021-01-15 13:52:31 +01:00
$networkmap_write = check_acl (
$config [ 'id_user' ],
$networkmap [ 'id_group' ],
'MW'
);
$networkmap_manage = check_acl (
$config [ 'id_user' ],
$networkmap [ 'id_group' ],
'MM'
);
if ( ! $networkmap_read
&& ! $networkmap_write
&& ! $networkmap_manage
) {
db_pandora_audit (
'ACL Violation' ,
'Trying to access networkmap'
);
include 'general/noaccess.php' ;
return '' ;
}
2019-03-07 18:57:48 +01:00
}
$user_readonly = ! $networkmap_write && ! $networkmap_manage ;
2019-03-18 18:11:54 +01:00
if ( isset ( $this -> idMap )
&& isset ( $this -> map [ '__simulated' ]) === false
) {
2019-03-11 15:09:31 +01:00
$output .= $this -> loadMapSkel ();
$output .= $this -> loadMapData ();
$output .= $this -> loadController ();
2019-03-26 15:27:45 +01:00
if ( ! $this -> noPopUp ) {
$output .= $this -> loadAdvancedInterface ();
}
2019-03-11 20:10:08 +01:00
} else {
2019-03-12 12:05:54 +01:00
// Simulated, no tmap entries.
2019-03-11 20:10:08 +01:00
$output .= $this -> loadMapSkel ();
$output .= $this -> loadMapData ();
$output .= $this -> loadController ();
2019-03-26 15:27:45 +01:00
if ( ! $this -> noPopUp ) {
$output .= $this -> loadSimpleInterface ();
}
2019-03-07 18:57:48 +01:00
}
2019-03-21 20:52:01 +01:00
$output .= '
< script type = " text/javascript " >
( function () {
var hidden = " hidden " ;
// Standards:
if ( hidden in document )
document . addEventListener ( " visibilitychange " , onchange );
else if (( hidden = " mozHidden " ) in document )
document . addEventListener ( " mozvisibilitychange " , onchange );
else if (( hidden = " webkitHidden " ) in document )
document . addEventListener ( " webkitvisibilitychange " , onchange );
else if (( hidden = " msHidden " ) in document )
document . addEventListener ( " msvisibilitychange " , onchange );
// IE 9 and lower:
else if ( " onfocusin " in document )
document . onfocusin = document . onfocusout = onchange ;
// All others:
else
window . onpageshow = window . onpagehide
= window . onfocus = window . onblur = onchange ;
function onchange ( evt ) {
// Reset all action status variables. Window is not in focus or visible.
flag_multiple_selection = false
disabled_drag_zoom = false ;
flag_multiple_selection_running = false ;
selected = undefined ;
}
// set the initial state (but only if browser supports the Page Visibility API)
if ( document [ hidden ] !== undefined )
onchange ({ type : document [ hidden ] ? " blur " : " focus " });
})();
</ script >
2019-03-22 03:56:31 +01:00
2019-03-21 20:52:01 +01:00
' ;
2019-03-07 18:57:48 +01:00
if ( $return === false ) {
echo $output ;
}
return $output ;
}
}