/**
  * Log when extra-debug is activated
  */
 static function logIfExtradebug($file, $message)
 {
     if (!PluginFusioninventoryConfig::isExtradebugActive()) {
         return;
     }
     Toolbox::logInFile($file, $message);
 }
 /**
  * Get logs of job
  *
  * @param array $task_ids list of tasks id
  * @return array
  */
 function getJoblogs($task_ids = array())
 {
     global $DB;
     $debug_mode = $_SESSION['glpi_use_mode'] == Session::DEBUG_MODE;
     $runclass = new PluginFusioninventoryTaskjobstate();
     $run_states = $runclass->getStateNames();
     $query_where = array();
     $query_where[] = "WHERE 1";
     if (isset($_SESSION['glpiactiveentities_string'])) {
         $query_where[] = getEntitiesRestrictRequest("AND", 'task');
     }
     if (is_array($task_ids) and count($task_ids) > 0) {
         $query_where[] = "AND task.`id` IN (" . implode(",", $task_ids) . ")";
     }
     // quickly filter empty WHERE entry
     $query_where = array_filter($query_where);
     $query_fields = array(array('task.id', 'task.`id`'), array('task.name', 'task.`name`'), array('job.id', 'job.`id`'), array('job.name', 'job.`name`'), array('job.method', 'job.`method`'), array('job.targets', 'job.`targets`'));
     $fieldmap = array();
     foreach ($query_fields as $index => $key) {
         $fieldmap[$key[0]] = $index;
     }
     $query_select = array();
     foreach ($query_fields as $index => $key) {
         $query_select[] = $key[1] . " AS '" . $key[0] . "'";
     }
     $query_joins = array();
     $query_joins['task'] = implode("\n", array("INNER JOIN `glpi_plugin_fusioninventory_tasks` as task", "  ON job.`plugin_fusioninventory_tasks_id` = task.`id`", "  AND task.`is_active` = 1"));
     $data_structure = array('query' => implode("\n", array("SELECT", implode(",\n", $query_select), "FROM `glpi_plugin_fusioninventory_taskjobs` as job", implode("\n", $query_joins), implode("\n", $query_where))), 'result' => null);
     $data_structure['result'] = $DB->query($data_structure['query']);
     //Results grouped by tasks > jobs > jobstates
     $logs = array();
     //Target cache (used to speed up data formatting)
     $targets_cache = array();
     $expanded = array();
     if (isset($_SESSION['plugin_fusioninventory_tasks_expanded'])) {
         $expanded = $_SESSION['plugin_fusioninventory_tasks_expanded'];
     }
     while ($result = $data_structure['result']->fetch_row()) {
         $task_id = $result[$fieldmap['task.id']];
         if (!array_key_exists($task_id, $logs)) {
             $logs[$task_id] = array('task_name' => $result[$fieldmap['task.name']], 'task_id' => $result[$fieldmap['task.id']], 'expanded' => false, 'jobs' => array());
         }
         if (isset($expanded[$task_id])) {
             $logs[$task_id]['expanded'] = $expanded[$task_id];
         }
         $job_id = $result[$fieldmap['job.id']];
         $jobs_handle =& $logs[$task_id]['jobs'];
         if (!array_key_exists($job_id, $jobs_handle)) {
             $jobs_handle[$job_id] = array('name' => $result[$fieldmap['job.name']], 'id' => $result[$fieldmap['job.id']], 'method' => $result[$fieldmap['job.method']], 'targets' => array());
         }
         $targets = importArrayFromDB($result[$fieldmap['job.targets']]);
         $targets_handle =& $jobs_handle[$job_id]['targets'];
         $agent_state_types = array('agents_prepared', 'agents_cancelled', 'agents_running', 'agents_success', 'agents_error', 'agents_notdone');
         if ($result[$fieldmap['job.method']] == 'networkinventory') {
             $pfNetworkinventory = new PluginFusioninventoryNetworkinventory();
             foreach ($targets as $keyt => $target) {
                 $item_type = key($target);
                 $items_id = current($target);
                 if ($item_type == 'PluginFusioninventoryIPRange') {
                     unset($targets[$keyt]);
                     // In this case get devices of this iprange
                     $deviceList = $pfNetworkinventory->getDevicesOfIPRange($items_id);
                     $targets = array_merge($targets, $deviceList);
                 }
             }
         }
         foreach ($targets as $target) {
             $item_type = key($target);
             $item_id = current($target);
             $target_id = $item_type . "_" . $item_id;
             if (isset($targets_cache[$target_id])) {
                 $item = $targets_cache[$target_id];
             } else {
                 $item = new $item_type();
                 $item->getFromDB($item_id);
                 $targets_cache[$target_id] = $item;
             }
             $targets_handle[$target_id] = array('id' => $item->fields['id'], 'name' => $item->fields['name'], 'type_name' => $item->getTypeName(), 'item_link' => $item->getLinkUrl(), 'counters' => array(), 'agents' => array());
             // create agent states counter lists
             foreach ($agent_state_types as $type) {
                 $targets_handle[$target_id]['counters'][$type] = array();
             }
         }
     }
     // Query fields mapping used to easily select fields by name
     $query_fields = array(array('task.id', 'task.`id`'), array('task.name', 'task.`name`'), array('job.id', 'job.`id`'), array('job.name', 'job.`name`'), array('job.method', 'job.`method`'), array('agent.id', 'agent.`id`'), array('agent.name', 'agent.`name`'), array('run.id', 'run.`id`'), array('run.itemtype', 'run.`itemtype`'), array('run.items_id', 'run.`items_id`'), array('run.state', 'run.`state`'), array('log.last_date', 'log.`date`'), array('log.last_timestamp', 'UNIX_TIMESTAMP(log.`date`)'), array('log.last_id', 'log.`id`'), array('log.last_comment', 'log.`comment`'));
     $fieldmap = array();
     foreach ($query_fields as $index => $key) {
         $fieldmap[$key[0]] = $index;
     }
     $query_select = array();
     foreach ($query_fields as $index => $key) {
         $query_select[] = $key[1] . " AS '" . $key[0] . "'";
     }
     $query_joins = array();
     $query_joins['max_run'] = implode("\n", array("INNER JOIN (", "  SELECT", "     MAX(run.`id`) AS max_id,", "     run.`plugin_fusioninventory_agents_id`,", "     run.`plugin_fusioninventory_taskjobs_id`,", "     run.`items_id`, run.`itemtype`,", "     MAX(log.`id`) AS max_log_id", "  FROM `glpi_plugin_fusioninventory_taskjobstates` AS run", "  LEFT JOIN `glpi_plugin_fusioninventory_taskjoblogs` AS log", "  ON log.`plugin_fusioninventory_taskjobstates_id` = run.`id`", "  GROUP BY", "     run.`plugin_fusioninventory_agents_id`,", "     run.`plugin_fusioninventory_taskjobs_id`,", "     run.`items_id`, run.`itemtype`", ") max_run ON max_run.`plugin_fusioninventory_agents_id` = agent.`id`"));
     $query_joins['run'] = implode("\n", array("INNER JOIN `glpi_plugin_fusioninventory_taskjobstates` AS run", "  ON max_run.`max_id` = run.`id`"));
     $query_joins['log'] = implode("\n", array("LEFT JOIN `glpi_plugin_fusioninventory_taskjoblogs` as log", "  ON log.`id` = max_run.`max_log_id`"));
     $query_joins['job'] = implode("\n", array("INNER JOIN `glpi_plugin_fusioninventory_taskjobs` AS job", "  ON job.`id` = run.`plugin_fusioninventory_taskjobs_id`"));
     $query_joins['task'] = implode("\n", array("INNER JOIN `glpi_plugin_fusioninventory_tasks` as task", "  ON job.`plugin_fusioninventory_tasks_id` = task.`id`"));
     $queries = array();
     /*
      * Get latest jobstates for agents
      */
     $queries['1_last_runs'] = array('query' => implode(" \n", array("SELECT", implode(",\n", $query_select), "FROM `glpi_plugin_fusioninventory_agents` AS agent", implode("\n", $query_joins), implode("\n", $query_where), "GROUP BY job.`id`, agent.`id`, run.`id`")), 'result' => null);
     /*
      * Get last finished jobstates (ie. `state` >= 3)
      */
     $query_joins['max_run'] = implode("\n", array("INNER JOIN (", "  SELECT", "     MAX(run.`id`) AS max_id,", "     run.`plugin_fusioninventory_agents_id`,", "     run.`plugin_fusioninventory_taskjobs_id`,", "     run.`items_id`, run.`itemtype`,", "     MAX(log.`id`) AS max_log_id", "  FROM `glpi_plugin_fusioninventory_taskjobstates` AS run", "  LEFT JOIN `glpi_plugin_fusioninventory_taskjoblogs` AS log", "  ON log.`plugin_fusioninventory_taskjobstates_id` = run.`id`", "  WHERE run.`state` IN ( " . implode(",", array(PluginFusioninventoryTaskjobstate::FINISHED, PluginFusioninventoryTaskjobstate::IN_ERROR)) . " )", "  GROUP BY", "     run.`plugin_fusioninventory_agents_id`,", "     run.`plugin_fusioninventory_taskjobs_id`,", "     run.`items_id`, run.`itemtype`", ") max_run ON max_run.`plugin_fusioninventory_agents_id` = agent.`id`"));
     $queries['2_finished_runs'] = array('query' => implode(" \n", array("SELECT", implode(",\n", $query_select), "FROM `glpi_plugin_fusioninventory_agents` AS agent", implode("\n", $query_joins), implode("\n", $query_where), "GROUP BY job.`id`, agent.`id`, run.`id`")), 'result' => null);
     $query_chrono = array("start" => microtime(true), "end" => 0);
     ksort($queries);
     foreach ($queries as $query_name => $contents) {
         $queries[$query_name]['result'] = $DB->query($contents['query']);
         $query_chrono['end'] = microtime(true);
         // For debug only
         //if ($debug_mode) {
         //   file_put_contents("/tmp/glpi_".$query_name.".sql",$contents['query']);
         //}
     }
     $agents = array();
     $format_chrono = array("start" => microtime(true), "end" => 0);
     foreach ($queries as $query_name => $contents) {
         if (!is_null($contents['result'])) {
             while ($result = $contents['result']->fetch_row()) {
                 // We need to check if the results are consistent with the view's structure gathered
                 // by the first query
                 $task_id = $result[$fieldmap['task.id']];
                 //if (!array_key_exists($task_id, $logs)) {
                 if (!isset($logs[$task_id])) {
                     continue;
                 }
                 $job_id = $result[$fieldmap['job.id']];
                 $jobs =& $logs[$task_id]['jobs'];
                 if (!isset($jobs[$job_id])) {
                     continue;
                 }
                 $target_id = $result[$fieldmap['run.itemtype']] . '_' . $result[$fieldmap['run.items_id']];
                 $targets =& $jobs[$job_id]['targets'];
                 if (!isset($targets[$target_id])) {
                     continue;
                 }
                 $counters =& $targets[$target_id]['counters'];
                 $agent_id = $result[$fieldmap['agent.id']];
                 $agents[$agent_id] = $result[$fieldmap['agent.name']];
                 if (!isset($targets[$target_id]['agents'][$agent_id])) {
                     $targets[$target_id]['agents'][$agent_id] = array();
                 }
                 $agent_state = '';
                 // Update counters
                 switch ($result[$fieldmap['run.state']]) {
                     case PluginFusioninventoryTaskjobstate::CANCELLED:
                         // We put this agent in the cancelled counter if it does not have any other job
                         // states.
                         if (!isset($counters['agents_prepared'][$agent_id]) and !isset($counters['agents_running'][$agent_id])) {
                             $counters['agents_cancelled'][$agent_id] = 1;
                             $agent_state = 'cancelled';
                         }
                         break;
                     case PluginFusioninventoryTaskjobstate::PREPARED:
                         // We put this agent in the prepared counter if it has not yet completed any job.
                         $counters['agents_prepared'][$agent_id] = 1;
                         $agent_state = 'prepared';
                         break;
                     case PluginFusioninventoryTaskjobstate::SERVER_HAS_SENT_DATA:
                     case PluginFusioninventoryTaskjobstate::AGENT_HAS_SENT_DATA:
                         // This agent is running so it must not be in any other counter
                         foreach ($agent_state_types as $type) {
                             if (isset($counters[$type][$agent_id])) {
                                 unset($counters[$type][$agent_id]);
                             }
                         }
                         $counters['agents_running'][$agent_id] = 1;
                         $agent_state = 'running';
                         break;
                     case PluginFusioninventoryTaskjobstate::IN_ERROR:
                         if (isset($counters['agents_success'][$agent_id])) {
                             unset($counters['agents_success'][$agent_id]);
                         }
                         $counters['agents_error'][$agent_id] = 1;
                         $agent_state = 'error';
                         if (isset($counters['agents_notdone'][$agent_id])) {
                             unset($counters['agents_notdone'][$agent_id]);
                         }
                         break;
                     case PluginFusioninventoryTaskjobstate::FINISHED:
                         if (isset($counters['agents_error'][$agent_id])) {
                             unset($counters['agents_error'][$agent_id]);
                         }
                         $counters['agents_success'][$agent_id] = 1;
                         $agent_state = 'success';
                         if (isset($counters['agents_notdone'][$agent_id])) {
                             unset($counters['agents_notdone'][$agent_id]);
                         }
                         break;
                 }
                 if (!isset($counters['agents_error'][$agent_id]) and !isset($counters['agents_success'][$agent_id])) {
                     $counters['agents_notdone'][$agent_id] = 1;
                 }
                 if (isset($counters['agents_running'][$agent_id]) or isset($counters['agents_prepared'][$agent_id])) {
                     unset($counters['agents_cancelled'][$agent_id]);
                 }
                 $targets[$target_id]['agents'][$agent_id][] = array('agent_id' => $agent_id, 'numstate' => $result[$fieldmap['run.state']], 'state' => $agent_state, 'jobstate_id' => $result[$fieldmap['run.id']], 'last_log_id' => $result[$fieldmap['log.last_id']], 'last_log_date' => $result[$fieldmap['log.last_date']], 'timestamp' => $result[$fieldmap['log.last_timestamp']], 'last_log' => $result[$fieldmap['log.last_comment']]);
             }
         }
     }
     $format_chrono['end'] = microtime(true);
     if ($debug_mode) {
         function tmp_display_log($log)
         {
             return "ID:" . $log['task_id'] . "(" . $log['task_name'] . ")";
         }
         if (PluginFusioninventoryConfig::isExtradebugActive()) {
             Toolbox::logDebug(array("tasks" => implode(',', array_map('tmp_display_log', $logs)), "row count" => count($logs), "Joblogs Query" => self::FormatChrono($query_chrono), "Format logs results" => self::FormatChrono($format_chrono)));
         }
     }
     return array('tasks' => $logs, 'agents' => $agents);
 }
 static function cronWakeupAgents($crontask)
 {
     global $DB;
     $wakeupArray = array();
     $tasks = array();
     //Get the maximum number of agent to wakeup,
     //as allowed in the general configuration
     $config = new PluginFusioninventoryConfig();
     $maxWakeUp = $config->getValue('wakeup_agent_max');
     $counter = 0;
     $continue = true;
     //Get all active timeslots
     $timeslot = new PluginFusioninventoryTimeslot();
     $timeslots = $timeslot->getCurrentActiveTimeslots();
     if (empty($timeslots)) {
         $query_timeslot = '';
     } else {
         $query_timeslot = "OR (`plugin_fusioninventory_timeslots_id` IN (" . implode(',', $timeslots) . "))";
     }
     //Get all active task requiring an agent wakeup
     //Check all tasks without timeslot or task with a current active timeslot
     $query = "SELECT `id`, `wakeup_agent_counter`, `wakeup_agent_time`, `last_agent_wakeup` \n                 FROM `glpi_plugin_fusioninventory_tasks` \n                 WHERE `wakeup_agent_time` > 0 \n                    AND `wakeup_agent_counter` > 0\n                    AND `is_active`='1' \n                    AND ((`plugin_fusioninventory_timeslots_id`='0') \n                    {$query_timeslot})";
     foreach ($DB->request($query) as $task) {
         if (!is_null($task['wakeup_agent_time'])) {
             //Do not wake up is last wake up in inferior to the minimum wake up interval
             $interval = time() - strtotime($task['last_agent_wakeup']);
             if ($interval < $task['wakeup_agent_time'] * MINUTE_TIMESTAMP) {
                 continue;
             }
         }
         //For each task, get a number of taskjobs at the PREPARED state
         //(the maximum is defined in wakeup_agent_counter)
         $query_states = "SELECT `taskjobstates`.`plugin_fusioninventory_agents_id`, \n                                 `tasks`.`id` as `taskID`, \n                                 `tasks`.`wakeup_agent_time`,\n                                 `tasks`.`last_agent_wakeup`\n                          FROM `glpi_plugin_fusioninventory_taskjobstates` as `taskjobstates`,\n                               `glpi_plugin_fusioninventory_taskjobs` as `taskjobs`\n                          LEFT JOIN `glpi_plugin_fusioninventory_tasks` as `tasks` \n                             ON `tasks`.`id`=`taskjobs`.`plugin_fusioninventory_tasks_id`\n                          WHERE `tasks`.`id`='" . $task['id'] . "' \n                             AND `taskjobs`.`id`=`taskjobstates`.`plugin_fusioninventory_taskjobs_id` \n                             AND `taskjobstates`.`state`='" . PluginFusioninventoryTaskjobstate::PREPARED . "' \n                          ORDER BY `taskjobstates`.`id` ASC LIMIT " . $task['wakeup_agent_counter'];
         foreach ($DB->request($query_states) as $state) {
             $agents_id = $state['plugin_fusioninventory_agents_id'];
             //Check if agent is already added to the list of agents to wake up
             if (!isset($wakeupArray[$agents_id])) {
                 //This agent must be woken up
                 $wakeupArray[$agents_id] = $agents_id;
                 $counter++;
             }
             //Store task ID
             if (!in_array($state['taskID'], $tasks)) {
                 $tasks[] = $state['taskID'];
             }
             //Do not process more than the maximum number of wakeup allowed in the configuration
             if ($counter >= $maxWakeUp) {
                 if (PluginFusioninventoryConfig::isExtradebugActive()) {
                     Toolbox::logDebug(__("Maximum number of agent wakeup reached", 'fusioninventory') . ":" . $maxWakeUp);
                 }
                 $continue = false;
                 break;
             }
         }
         //We've reached the maximum number of agents to wake up !
         if (!$continue) {
             break;
         }
     }
     //Number of agents successfully woken up
     $wokeup = 0;
     $myTask = new PluginFusioninventoryTask();
     if (!empty($tasks)) {
         //Update last wake up time each task
         $query_lastrun = "UPDATE `glpi_plugin_fusioninventory_tasks` \n                           SET `last_agent_wakeup`='" . $_SESSION['glpi_currenttime'] . "' \n                           WHERE `id` IN (" . implode(",", $tasks) . ")";
         $DB->query($query_lastrun);
         $agent = new PluginFusioninventoryAgent();
         //Try to wake up agents one by one
         foreach ($wakeupArray as $ID => $value) {
             $agent->getFromDB($ID);
             if ($agent->wakeUp()) {
                 $wokeup++;
             }
         }
     }
     $crontask->addVolume($wokeup);
     return true;
 }
 function __construct()
 {
     if (PluginFusioninventoryConfig::isExtradebugActive()) {
         $this->logFile = GLPI_LOG_DIR . '/fusioninventorycommunication.log';
     }
 }
 /**
  * Add logs
  *
  * @param $p_logs logs to write
  *
  * @return nothing (write text in log file)
  **/
 static function addLog($p_logs)
 {
     if ($_SESSION['glpi_use_mode'] == Session::DEBUG_MODE) {
         if (PluginFusioninventoryConfig::isExtradebugActive()) {
             file_put_contents(GLPI_LOG_DIR . '/pluginFusioninventory-communication.log', "\n" . time() . ' : ' . $p_logs, FILE_APPEND);
         }
     }
 }