<?php

/*
 * Copyright 2005 - 2025 Centreon (https://www.centreon.com/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * For more information : contact@centreon.com
 *
 */

use enshrined\svgSanitize\Sanitizer;

/**
 * Displays the SVG file in HTML.
 *
 * @param string $svgPath SVG file path from _CENTREON_PATH_
 * @param string $color Color to be used in SVG image
 * @param float $height Height of image
 * @param float $width Width of image
 * @example <?php displaySvg('www/img/centreon.svg', '#000', 50, 50); ?>
 */
function displaySvg(string $svgPath, string $color, float $height, float $width): void
{
    $path = pathinfo($svgPath);
    $svgPath = str_replace('.', '', $path['dirname']) . DIRECTORY_SEPARATOR . $path['basename'];
    $path = _CENTREON_PATH_ . DIRECTORY_SEPARATOR . $svgPath;
    if (file_exists($path)) {
        $sanitizer = new Sanitizer();
        $svg = file_get_contents($path);
        if ($svg === false) {
            echo 'Unable to get content of file: ' . $path;
        } else {
            $cleanSvg = str_replace('"', "'", $sanitizer->sanitize($svg));
            $cleanSvg = str_replace("\n", '', $cleanSvg);
            $cleanSvg = str_replace('<svg ', "<svg height='{$height}' width='{$width}' ", $cleanSvg);
            echo "<span style='fill:{$color}; vertical-align: middle'>" . $cleanSvg . '</span>';
        }
    } else {
        echo 'SVG file not found: ' . $svgPath;
    }
}

/**
 * Return the SVG file.
 *
 * @param string $svgPath SVG file path from _CENTREON_PATH_
 * @param string $color Color to be used in SVG image
 * @param float $height Height of image
 * @param float $width Width of image
 * @example <?php returnSvg('www/img/centreon.svg', '#000', 50, 50); ?>
 */
function returnSvg(string $svgPath, string $color, float $height, float $width): string
{
    $path = pathinfo($svgPath);
    $svgPath = str_replace('.', '', $path['dirname']) . DIRECTORY_SEPARATOR . $path['basename'];
    $path = _CENTREON_PATH_ . DIRECTORY_SEPARATOR . $svgPath;
    if (file_exists($path)) {
        $data = file_get_contents($path);
        $data = str_replace('<svg ', "<svg height='{$height}' width='{$width}' ", $data);

        return "<span style='fill:{$color} ; vertical-align: middle'>" . $data . '</span>';
    }

    return 'SVG file not found: ' . $svgPath;
}

// Form Rules
function slash($elem = null)
{
    if ($elem) {
        return rtrim($elem, '/') . '/';
    }
}

/*
 * function table_not_exists()
 * - This function test if a table exist in database.
 *
 * @param	string	$table_name (the name of the table to test)
 * @return	int		0 			(return 0 if the table exists)
 */

function isUserAdmin($sid = null)
{
    global $pearDB;
    if (! isset($sid)) {
        return;
    }

    $DBRESULT = $pearDB->prepare(
        <<<'SQL'
            SELECT contact_admin, contact_id FROM session, contact
            WHERE session.session_id = ? AND contact.contact_id = session.user_id
            SQL
    );
    $DBRESULT->execute([CentreonDB::escape($sid)]);
    $admin = $DBRESULT->fetchRow();
    $DBRESULT->closeCursor();

    if ($admin['contact_admin']) {
        return 1;
    }

    return 0;
}

function myDecode($data)
{
    if (is_string($data)) {
        $data = html_entity_decode($data, ENT_QUOTES, 'UTF-8');
    }

    return $data;
}

function myEncode($data)
{
    if (is_string($data)) {
        $data = htmlentities($data);
    }

    return $data;
}

function isPositiveInteger($value)
{
    return preg_match('/^\d+$/', $value);
}

function getStatusColor($pearDB)
{
    $colors = [];
    $DBRESULT = $pearDB->query("SELECT * FROM `options` WHERE `key` LIKE 'color%'");
    while ($c = $DBRESULT->fetchRow()) {
        $colors[$c['key']] = myDecode($c['value']);
    }
    $DBRESULT->closeCursor();

    return $colors;
}

function tidySearchKey($search, $advanced_search)
{
    if ($advanced_search == 1) {
        if (isset($search) && ! strstr($search, '*') && ! strstr($search, '%')) {
            $search = "'" . $search . "'";
        } elseif (
            isset($search, $search[0], $search[strlen($search) - 1])
            && $search[0] == '%'
            && $search[strlen($search) - 1] == '%'
        ) {
            $search = str_replace('%', '', $search);
        } elseif (strpos($search, '%')) {
            $search = str_replace('%', '*', $search);
        }
    }

    return $search;
}

//
// # SMARTY

/**
 * NOT REMOVE THIS FUNCTION - Used in centreon-modules
 *
 * Allows to load Smarty's configuration in relation to a path
 *
 * @param string|null $path [$path=null] Path to the default template directory
 * @param object|null $tpl [$tpl=null] A Smarty instance
 * @param string|null $subDir [$subDir=null] A subdirectory of path
 *
 * @throws SmartyException
 * @return SmartyBC
 *
 * @deprecated Instead use {@see SmartyBC::createSmartyTemplate()}
 * @see        SmartyBC::createSmartyTemplate()
 */
function initSmartyTpl(?string $path = null, ?object &$tpl = null, ?string $subDir = null): SmartyBC
{
    return SmartyBC::createSmartyTemplate($path, $subDir);
}

/**
 * NOT REMOVE THIS FUNCTION - Used in centreon-modules
 *
 * This function is mainly used in widgets
 *
 * @param string|null $path
 * @param object|null $tpl
 * @param string|null $subDir
 * @param string|null $centreonPath
 *
 * @throws SmartyException
 * @return SmartyBC
 *
 * @deprecated Instead use {@see SmartyBC::createSmartyTemplate()}
 * @see        SmartyBC::createSmartyTemplate()
 */
function initSmartyTplForPopup(?string $path = null, ?object $tpl = null, ?string $subDir = null, ?string $centreonPath = null): SmartyBC
{
    return SmartyBC::createSmartyTemplate($path, $subDir);
}

// FORM VALIDATION

function myTrim($str)
{
    global $form;
    $str = rtrim($str, '\\');

    return trim($str);
}

/**
 * @param string $value
 * @return string
 */
function limitNotesLength(string $value): string
{
    return substr($value, 0, 512);
}

/**
 * @param string $value
 * @return string
 */
function limitUrlLength(string $value): string
{
    return substr($value, 0, 2048);
}

function getMyHostName($host_id = null)
{
    global $pearDB;

    if (! $host_id) {
        return;
    }
    $query = 'SELECT host_name FROM host WHERE host_id = :host_id LIMIT 1';
    $statement = $pearDB->prepare($query);
    $statement->bindValue(':host_id', (int) $host_id, PDO::PARAM_INT);
    $statement->execute();
    $row = $statement->fetchRow();
    if ($row['host_name']) {
        return $row['host_name'];
    }
}

function getMyHostField($host_id, $field)
{
    if (! $host_id) {
        return;
    }
    global $pearDB;

    $query = 'SELECT host_tpl_id FROM host_template_relation WHERE host_host_id = :host_id ORDER BY `order` ASC';
    $statement = $pearDB->prepare($query);
    $statement->bindValue(':host_id', (int) $host_id, PDO::PARAM_INT);
    $statement->execute();
    $hostStatement = $pearDB->prepare('SELECT `' . $field . '` FROM host WHERE host_id = :host_tpl_id');
    while ($row = $statement->fetchRow()) {
        $hostStatement->bindValue(':host_tpl_id', (int) $row['host_tpl_id'], PDO::PARAM_INT);
        $hostStatement->execute();
        while ($row2 = $hostStatement->fetchRow()) {
            if (isset($row2[$field]) && $row2[$field]) {
                return $row2[$field];
            }
            if ($tmp = getMyHostField($row['host_tpl_id'], $field)) {
                return $tmp;
            }
        }
    }

    return null;
}

// This functions is called recursively until it finds an ehi field

function getMyHostExtendedInfoFieldFromMultiTemplates($host_id, $field)
{
    if (! $host_id) {
        return null;
    }
    global $pearDB;
    $rq = 'SELECT host_tpl_id '
        . 'FROM host_template_relation '
        . 'WHERE host_host_id = :host_host_id '
        . 'ORDER BY `order`';
    $statement = $pearDB->prepare($rq);
    $statement->bindValue(':host_host_id', (int) $host_id, PDO::PARAM_INT);
    $statement->execute();
    $rq2 = 'SELECT ehi.`' . $field . '` '
        . ' FROM extended_host_information ehi '
        . 'WHERE ehi.host_host_id = :host_host_id LIMIT 1';
    $statement2 = $pearDB->prepare($rq2);
    while ($row = $statement->fetchRow()) {
        $statement2->bindValue(':host_host_id', (int) $row['host_tpl_id'], PDO::PARAM_INT);
        $statement2->execute();

        $row2 = $statement2->fetchRow();
        if (isset($row2[$field]) && $row2[$field]) {
            return $row2[$field];
        }
        if ($result_field = getMyHostExtendedInfoFieldFromMultiTemplates($row['host_tpl_id'], $field)) {
            return $result_field;
        }
    }

    return null;
}

function getMyHostMacroFromMultiTemplates($host_id, $field)
{
    if (! $host_id) {
        return null;
    }
    global $pearDB;
    $statement = $pearDB->prepare('SELECT host_tpl_id '
        . 'FROM host_template_relation '
        . 'WHERE host_host_id = :host_host_id '
        . 'ORDER BY `order`');
    $statement->bindValue(':host_host_id', (int) $host_id, PDO::PARAM_INT);
    $statement->execute();
    $statement2 = $pearDB->prepare('SELECT macro.host_macro_value '
        . 'FROM on_demand_macro_host macro '
        . 'WHERE macro.host_host_id = :host_host_id  AND macro.host_macro_name = :field LIMIT 1');
    while ($row = $statement->fetchRow()) {
        $statement2->bindValue(':host_host_id', (int) $row['host_tpl_id'], PDO::PARAM_INT);
        $statement2->bindValue(':field', '$_HOST' . $field . '$', PDO::PARAM_STR);
        $statement2->execute();
        $row2 = $statement2->fetchRow();
        if (isset($row2['host_macro_value']) && $row2['host_macro_value']) {
            $macroValue = str_replace('#S#', '/', $row2['host_macro_value']);
            $macroValue = str_replace('#BS#', '\\', $macroValue);

            return $macroValue;
        }
        if ($result_field = getMyHostMacroFromMultiTemplates($row['host_tpl_id'], $field)) {
            $macroValue = str_replace('#S#', '/', $result_field);
            $macroValue = str_replace('#BS#', '\\', $macroValue);

            return $macroValue;
        }
    }

    return null;
}

function getMyServiceCategories($service_id = null)
{
    global $pearDB, $oreon;
    if (! $service_id) {
        return;
    }
    $tab = [];
    while (1) {
        $statement = $pearDB->prepare('SELECT sc.sc_id FROM service_categories_relation scr, service_categories sc '
            . "WHERE scr.service_service_id = :service_id AND sc.sc_id = scr.sc_id AND sc.sc_activate = '1'");
        $statement->bindValue(':service_id', (int) $service_id, PDO::PARAM_INT);
        $statement->execute();
        if ($statement->rowCount()) {
            $tabSC = [];
            while ($row = $statement->fetchRow()) {
                $tabSC[$row['sc_id']] = $row['sc_id'];
            }

            return $tabSC;
        }
        $statement = $pearDB->prepare('SELECT service_template_model_stm_id '
            . ' FROM service WHERE service_id = :service_id');
        $statement->bindValue(':service_id', (int) $service_id, PDO::PARAM_INT);
        $statement->execute();
        $row = $statement->fetchRow();
        if ($row['service_template_model_stm_id']) {
            if (isset($tab[$row['service_template_model_stm_id']])) {
                break;
            }
            $service_id = $row['service_template_model_stm_id'];
            $tab[$service_id] = 1;
        } else {
            return [];
        }

    }
}

function getMyCategorieName($sc_id = null)
{
    if (! $sc_id) {
        return;
    }
    global $pearDB, $oreon;
    $statement = $pearDB->prepare('SELECT sc_name FROM service_categories WHERE sc_id = :sc_id');
    $statement->bindValue(':sc_id', (int) $sc_id, PDO::PARAM_INT);
    $statement->execute();
    $row = $statement->fetchRow();

    return $row['sc_name'];
}

function getMyServiceMacro($service_id, $field)
{
    if (! $service_id) {
        return;
    }
    global $pearDB;
    $query = 'SELECT macro.svc_macro_value '
        . 'FROM on_demand_macro_service macro '
        . 'WHERE macro.svc_svc_id = :svc_svc_id
        AND macro.svc_macro_name = :svc_macro_name LIMIT 1';
    $statement = $pearDB->prepare($query);
    $statement->bindValue(':svc_svc_id', (int) $service_id, PDO::PARAM_INT);
    $statement->bindValue(':svc_macro_name', '$_SERVICE' . $field . '$', PDO::PARAM_STR);
    $statement->execute();
    $row = $statement->fetch(PDO::FETCH_ASSOC);
    if (isset($row['svc_macro_value']) && $row['svc_macro_value']) {
        $macroValue = str_replace('#S#', '/', $row['svc_macro_value']);
        $macroValue = str_replace('#BS#', '\\', $macroValue);

        return $macroValue;
    }
    $service_id = getMyServiceField($service_id, 'service_template_model_stm_id');

    return getMyServiceMacro($service_id, $field);
}

function getMyHostExtendedInfoField($host_id, $field)
{
    if (! $host_id) {
        return;
    }
    global $pearDB, $oreon;

    $rq = 'SELECT ehi.`' . $field . '` '
        . 'FROM extended_host_information ehi '
        . 'WHERE ehi.host_host_id = :host_id LIMIT 1';
    $statement = $pearDB->prepare($rq);
    $statement->bindValue(':host_id', (int) $host_id, PDO::PARAM_INT);
    $statement->execute();
    $row = $statement->fetchRow();
    if (isset($row[$field]) && $row[$field]) {
        return $row[$field];
    }

    return getMyHostExtendedInfoFieldFromMultiTemplates($host_id, $field);
}

function getMyHostExtendedInfoImage($host_id, $field, $flag1stLevel = null, $antiLoop = null)
{
    global $pearDB, $oreon;

    if (! $host_id) {
        return;
    }

    if (isset($flag1stLevel) && $flag1stLevel) {
        $rq = 'SELECT ehi.`' . $field . '` '
            . 'FROM extended_host_information ehi '
            . 'WHERE ehi.host_host_id = :host_host_id LIMIT 1';
        $statement = $pearDB->prepare($rq);
        $statement->bindValue(':host_host_id', (int) $host_id, PDO::PARAM_INT);
        $statement->execute();
        $row = $statement->fetch(PDO::FETCH_ASSOC);
        if (isset($row[$field]) && $row[$field]) {
            $query = 'SELECT img_path, dir_alias FROM view_img vi, view_img_dir vid, view_img_dir_relation vidr '
                . 'WHERE vi.img_id = :img_id
                AND vidr.img_img_id = vi.img_id AND vid.dir_id = vidr.dir_dir_parent_id LIMIT 1';
            $statement = $pearDB->prepare($query);
            $statement->bindValue(':img_id', (int) $row[$field], PDO::PARAM_INT);
            $statement->execute();
            $row2 = $statement->fetch(PDO::FETCH_ASSOC);
            if (isset($row2['dir_alias'], $row2['img_path'])   && $row2['dir_alias'] && $row2['img_path']) {
                return $row2['dir_alias'] . '/' . $row2['img_path'];
            }
        } elseif ($result_field = getMyHostExtendedInfoImage($host_id, $field)) {
            return $result_field;
        }

        return null;
    }
    $rq = 'SELECT host_tpl_id '
        . 'FROM host_template_relation '
        . 'WHERE host_host_id = :host_host_id '
        . 'ORDER BY `order`';
    $htStatement = $pearDB->prepare($rq);
    $htStatement->bindValue(':host_host_id', (int) $host_id, PDO::PARAM_INT);
    $htStatement->execute();
    $rq2 = 'SELECT `' . $field . '` '
           . 'FROM extended_host_information ehi '
           . 'WHERE ehi.host_host_id = :host_host_id LIMIT 1';
    $ehiStatement = $pearDB->prepare($rq2);
    $query = 'SELECT img_path, dir_alias FROM view_img vi, view_img_dir vid, view_img_dir_relation vidr '
             . 'WHERE vi.img_id = :img_id
                 AND vidr.img_img_id = vi.img_id AND vid.dir_id = vidr.dir_dir_parent_id LIMIT 1';
    $imgStatement = $pearDB->prepare($query);
    while ($row = $htStatement->fetch(PDO::FETCH_ASSOC)) {
        $ehiStatement->bindValue(':host_host_id', (int) $row['host_tpl_id'], PDO::PARAM_INT);
        $ehiStatement->execute();
        $row2 = $ehiStatement->fetch(PDO::FETCH_ASSOC);
        if (isset($row2[$field]) && $row2[$field]) {
            $imgStatement->bindValue(':img_id', (int) $row2[$field], PDO::PARAM_INT);
            $imgStatement->execute();
            $row3 = $imgStatement->fetch(PDO::FETCH_ASSOC);
            if (isset($row3['dir_alias'], $row3['img_path'])   && $row3['dir_alias'] && $row3['img_path']) {
                return $row3['dir_alias'] . '/' . $row3['img_path'];
            }
        } elseif (isset($antiLoop) && $antiLoop) {
            if ($antiLoop != $row['host_tpl_id']) {
                if ($result_field = getMyHostExtendedInfoImage($row['host_tpl_id'], $field, null, $antiLoop)) {
                    return $result_field;
                }
            }
        } elseif ($result_field = getMyHostExtendedInfoImage(
            $row['host_tpl_id'],
            $field,
            null,
            $row['host_tpl_id']
        )) {
            return $result_field;
        }
    }

    return null;
}

function getMyHostMultipleTemplateModels($host_id = null)
{
    if (! $host_id) {
        return [];
    }

    global $pearDB;
    $tplArr = [];
    $query = 'SELECT host_tpl_id FROM `host_template_relation` WHERE host_host_id = :host_id ORDER BY `order`';
    $statement0 = $pearDB->prepare($query);
    $statement0->bindValue(':host_id', (int) $host_id, PDO::PARAM_INT);
    $statement0->execute();
    $statement = $pearDB->prepare('SELECT host_name FROM host WHERE host_id = :host_id LIMIT 1');
    while ($row = $statement0->fetchRow()) {
        $statement->bindValue(':host_id', (int) $row['host_tpl_id'], PDO::PARAM_INT);
        $statement->execute();
        $hTpl = $statement->fetch(PDO::FETCH_ASSOC);
        $tplArr[$row['host_tpl_id']] = html_entity_decode($hTpl['host_name'], ENT_QUOTES, 'UTF-8');
    }

    return $tplArr;
}

//
// # HOST GROUP

function getMyHostGroupName($hg_id = null)
{
    if (! $hg_id) {
        return;
    }
    global $pearDB;

    $query = 'SELECT hg_name FROM hostgroup WHERE hg_id = :hg_id LIMIT 1';
    $statement = $pearDB->prepare($query);
    $statement->bindValue(':hg_id', (int) $hg_id, PDO::PARAM_INT);
    $statement->execute();
    $row = $statement->fetchRow();
    if ($row['hg_name']) {
        return html_entity_decode($row['hg_name'], ENT_QUOTES, 'UTF-8');
    }

    return null;
}

/* * ******************************
 * Get all host for a specific hostgroup
 *
 * @var hostgroup id
 * @var search string
 *
 * @return list of host
 */

function getMyHostGroupHosts($hg_id = null, $searchHost = null, $level = 1)
{
    global $pearDB;

    if (! $hg_id) {
        return;
    }

    $searchSTR = '';
    if (isset($searchHost) && $searchHost != '') {
        $searchSTR = " AND h.host_name LIKE '%" . CentreonDB::escape($searchHost) . "%' ";
    }
    $hosts = [];
    $statement = $pearDB->prepare('SELECT hgr.host_host_id '
        . 'FROM hostgroup_relation hgr, host h '
        . 'WHERE hgr.hostgroup_hg_id = :hostgroup_hg_id '
        . "AND h.host_id = hgr.host_host_id {$searchSTR} "
        . 'ORDER by h.host_name');
    $statement->bindValue(':hostgroup_hg_id', (int) $hg_id, PDO::PARAM_INT);
    $statement->execute();
    while ($elem = $statement->fetch(PDO::FETCH_ASSOC)) {
        $hosts[$elem['host_host_id']] = $elem['host_host_id'];
    }
    $statement->closeCursor();
    unset($elem);

    if ($level) {
        $hgHgCache = setHgHgCache($pearDB);
        $hostgroups = getMyHostGroupHostGroups($hg_id);
        if (isset($hostgroups) && count($hostgroups)) {
            foreach ($hostgroups as $hg_id2) {
                $tmp = getMyHostGroupHosts($hg_id2, '', 1);
                foreach ($tmp as $id) {
                    $hosts[$id] = $id;
                }
                unset($tmp);
            }
        }
    }

    return $hosts;
}

function setHgHgCache($pearDB)
{
    $hgHgCache = [];
    $DBRESULT = $pearDB->query('SELECT /* SQL_CACHE */ hg_parent_id, hg_child_id FROM hostgroup_hg_relation');
    while ($data = $DBRESULT->fetchRow()) {
        if (! isset($hgHgCache[$data['hg_parent_id']])) {
            $hgHgCache[$data['hg_parent_id']] = [];
        }
        $hgHgCache[$data['hg_parent_id']][$data['hg_child_id']] = 1;
    }
    $DBRESULT->closeCursor();
    unset($data);

    return $hgHgCache;
}

function getMyHostGroupHostGroups($hg_id = null)
{
    global $pearDB;

    if (! $hg_id) {
        return;
    }

    $hosts = [];

    $statement = $pearDB->prepare('SELECT hg_child_id '
        . 'FROM hostgroup_hg_relation, hostgroup '
        . 'WHERE hostgroup_hg_relation.hg_parent_id = :hg_parent_id '
        . 'AND hostgroup.hg_id = hostgroup_hg_relation.hg_child_id '
        . 'ORDER BY hostgroup.hg_name');
    $statement->bindValue(':hg_parent_id', (int) $hg_id, PDO::PARAM_INT);
    $statement->execute();
    while ($elem = $statement->fetch(PDO::FETCH_ASSOC)) {
        $hosts[$elem['hg_child_id']] = $elem['hg_child_id'];
    }
    $statement->closeCursor();
    unset($elem);

    return $hosts;
}

//
// # SERVICE GROUP

function getMyServiceGroupServices($sg_id = null)
{
    global $pearDB;
    if (! $sg_id) {
        return;
    }
    // ServiceGroups by host
    $svs = [];
    $statement = $pearDB->prepare('SELECT service_description, service_id, host_host_id, host_name '
        . 'FROM servicegroup_relation, service, host '
        . 'WHERE servicegroup_sg_id = :sg_id '
        . 'AND servicegroup_relation.servicegroup_sg_id = servicegroup_sg_id '
        . 'AND service.service_id = servicegroup_relation.service_service_id '
        . 'AND servicegroup_relation.host_host_id = host.host_id '
        . 'AND servicegroup_relation.host_host_id IS NOT NULL');
    $statement->bindValue(':sg_id', (int) $sg_id, PDO::PARAM_INT);
    $statement->execute();
    while ($elem = $statement->fetchRow()) {
        $svs[$elem['host_host_id'] . '_' . $elem['service_id']]
            = db2str($elem['service_description']) . ':::' . $elem['host_name'];
    }

    // ServiceGroups by hostGroups
    $statement1 = $pearDB->prepare('SELECT service_description, service_id, hostgroup_hg_id, hg_name '
        . 'FROM servicegroup_relation, service, hostgroup '
        . 'WHERE servicegroup_sg_id = :sg_id '
        . 'AND servicegroup_relation.servicegroup_sg_id = servicegroup_sg_id '
        . 'AND service.service_id = servicegroup_relation.service_service_id '
        . 'AND servicegroup_relation.hostgroup_hg_id = hostgroup.hg_id '
        . 'AND servicegroup_relation.hostgroup_hg_id IS NOT NULL');
    $statement1->bindValue(':sg_id', (int) $sg_id, PDO::PARAM_INT);
    $statement1->execute();
    while ($elem = $statement1->fetchRow()) {
        $hosts = getMyHostGroupHosts($elem['hostgroup_hg_id']);
        foreach ($hosts as $key => $value) {
            $svs[$key . '_' . $elem['service_id']] = db2str($elem['service_description']) . ':::' . $value;
        }
    }
    $statement1->closeCursor();

    return $svs;
}

//
// # SERVICE

function getMyServiceField($service_id, $field)
{
    if (! $service_id) {
        return;
    }
    global $pearDB;
    $tab = [];

    while (1) {
        $statement = $pearDB->prepare('SELECT `' . $field . '` , service_template_model_stm_id '
            . 'FROM service WHERE service_id = :service_id LIMIT 1');
        $statement->bindValue(':service_id', (int) $service_id, PDO::PARAM_INT);
        $statement->execute();
        $row = $statement->fetchRow();
        if ($row[$field]) {
            return $row[$field];
        }
        if ($row['service_template_model_stm_id']) {
            if (isset($tab[$row['service_template_model_stm_id']])) {
                break;
            }
            $service_id = $row['service_template_model_stm_id'];
            $tab[$service_id] = 1;
        } else {
            break;
        }
    }
}

function getMyServiceExtendedInfoField($service_id, $field)
{
    if (! $service_id) {
        return;
    }
    global $pearDB;

    $tab = [];
    while (1) {
        $statement = $pearDB->prepare('SELECT `extended_service_information`.`' . $field . '` ,'
            . ' `service`.`service_template_model_stm_id` '
            . 'FROM `service`, `extended_service_information` '
            . 'WHERE `extended_service_information`.`service_service_id` =:service_id '
            . 'AND `service`.`service_id` = :service_id LIMIT 1');

        $statement->bindValue(':service_id', (int) $service_id, PDO::PARAM_INT);
        $statement->execute();

        if ($row = $statement->fetch()) {
            if ($row[$field]) {
                return $row[$field];
            }
            if ($row['service_template_model_stm_id']) {
                if (isset($tab[$row['service_template_model_stm_id']])) {
                    break;
                }
                $service_id = $row['service_template_model_stm_id'];
                $tab[$service_id] = 1;
            } else {
                break;
            }
        } else {
            break;
        }
    }
}

function getMyServiceName($service_id = null)
{
    if (! $service_id) {
        return;
    }
    global $pearDB;
    $tab = [];

    while (1) {
        $statement = $pearDB->prepare('SELECT service_description, service_template_model_stm_id FROM service '
            . ' WHERE service_id = :service_id LIMIT 1');
        $statement->bindValue(':service_id', (int) $service_id, PDO::PARAM_INT);
        $statement->execute();
        $row = $statement->fetchRow();
        if ($row['service_description']) {
            return html_entity_decode(db2str($row['service_description']), ENT_QUOTES, 'UTF-8');
        }
        if ($row['service_template_model_stm_id']) {
            if (isset($tab[$row['service_template_model_stm_id']])) {
                break;
            }
            $service_id = $row['service_template_model_stm_id'];
            $tab[$service_id] = 1;
        } else {
            break;
        }
    }
}

function getMyServiceAlias($service_id = null)
{
    if (! $service_id) {
        return;
    }
    global $pearDB;

    $tab = [];

    while (1) {
        $statement = $pearDB->prepare('SELECT service_alias, service_template_model_stm_id FROM service '
            . 'WHERE service_id = :service_id LIMIT 1');
        $statement->bindValue(':service_id', (int) $service_id, PDO::PARAM_INT);
        $statement->execute();
        $row = $statement->fetchRow();
        if ($row['service_alias']) {
            return html_entity_decode(db2str($row['service_alias']), ENT_QUOTES, 'UTF-8');
        }
        if ($row['service_template_model_stm_id']) {
            if (isset($tab[$row['service_template_model_stm_id']])) {
                break;
            }
            $service_id = $row['service_template_model_stm_id'];
            $tab[$service_id] = 1;
        } else {
            break;
        }
    }
}

function getMyServiceGraphID($service_id = null)
{
    if (! $service_id) {
        return;
    }
    global $pearDB;

    $tab = [];
    while (1) {
        $statement = $pearDB->prepare('SELECT esi.graph_id, service_template_model_stm_id'
            . ' FROM service, extended_service_information esi '
            . 'WHERE service_id = :service_id AND esi.service_service_id = service_id LIMIT 1');
        $statement->bindValue(':service_id', (int) $service_id, PDO::PARAM_INT);
        $statement->execute();
        $row = $statement->fetchRow();
        if ($row['graph_id']) {
            return $row['graph_id'];
        }
        if ($row['service_template_model_stm_id']) {
            if (isset($tab[$row['service_template_model_stm_id']])) {
                break;
            }
            $service_id = $row['service_template_model_stm_id'];
            $tab[$service_id] = 1;
        } else {
            break;
        }
    }

    return null;
}

function getMyServiceIDStorage($service_description, $host_id)
{
    $dbb = new CentreonDB('centstorage');
    $statement = $dbb->prepare('SELECT s.service_id FROM services s '
        . ' WHERE (s.description = :service_description
                        OR s.description = :utf8_uncoded_service_description ) '
        . ' AND s.host_id = :host_id LIMIT 1');
    $statement->bindValue(':service_description', $service_description, PDO::PARAM_STR);
    $statement->bindValue(':utf8_uncoded_service_description', mb_convert_encoding($service_description, 'UTF-8', 'ISO-8859-1'), PDO::PARAM_STR);
    $statement->bindValue(':host_id', (int) $host_id, PDO::PARAM_INT);
    $statement->execute();
    $row = $statement->fetchRow();
    if ($row['service_id']) {
        return $row['service_id'];
    }
}

function getMyServiceID($service_description = null, $host_id = null, $hg_id = null)
{
    if (! $service_description && (! $host_id || ! $hg_id)) {
        return;
    }
    global $pearDB;

    $service_description = str2db($service_description);
    if ($host_id) {
        $statement = $pearDB->prepare('SELECT service_id FROM service, host_service_relation hsr '
            . 'WHERE hsr.host_host_id = :host_host_id AND hsr.service_service_id = service_id '
            . 'AND (service_description = :service_description OR'
            . ' service_description = :utf8_encoded_service_description ) LIMIT 1');
        $statement->bindValue(':host_host_id', (int) $host_id, PDO::PARAM_INT);
        $statement->bindValue(':utf8_encoded_service_description', mb_convert_encoding($service_description, 'UTF-8', 'ISO-8859-1'), PDO::PARAM_STR);
        $statement->bindValue(':service_description', $service_description, PDO::PARAM_STR);
        $statement->execute();
        $row = $statement->fetchRow();
        // Service is directely link to a host, no problem
        if ($row['service_id']) {
            return $row['service_id'];
        }
        // The Service might be link with a HostGroup
        $statement1 = $pearDB->prepare('SELECT service_id '
            . ' FROM hostgroup_relation hgr, service, host_service_relation hsr'
            . ' WHERE hgr.host_host_id = :host_host_id AND hsr.hostgroup_hg_id = hgr.hostgroup_hg_id'
            . ' AND service_id = hsr.service_service_id AND service_description = :service_description');

        $statement1->bindValue(':host_host_id', (int) $host_id, PDO::PARAM_INT);
        $statement1->bindValue(':service_description', $service_description, PDO::PARAM_STR);
        $statement1->execute();
        $row = $statement1->fetchRow();
        if ($row['service_id']) {
            return $row['service_id'];
        }
    }
    if ($hg_id) {
        $statement2 = $pearDB->prepare('SELECT service_id FROM service, host_service_relation hsr '
            . 'WHERE hsr.hostgroup_hg_id = :hostgroup_hg_id AND hsr.service_service_id = service_id '
            . 'AND service_description = :service_description LIMIT 1');

        $statement2->bindValue(':hostgroup_hg_id', (int) $hg_id, PDO::PARAM_INT);
        $statement2->bindValue(':service_description', $service_description, PDO::PARAM_STR);
        $statement2->execute();

        $row = $statement2->fetchRow();
        if ($row['service_id']) {
            return $row['service_id'];
        }
    }

    return null;
}

function getMyHostServices($host_id = null, $search = 0)
{
    global $pearDB;

    if (! $host_id) {
        return;
    }

    $hSvs = [];

    // Get Services attached to hosts
    if ($search !== 0) {
        $statement = $pearDB->prepare('SELECT service_id, service_description'
            . ' FROM service, host_service_relation hsr '
            . 'WHERE hsr.host_host_id = :host_id AND hsr.service_service_id = service_id '
            . 'AND service_description LIKE :service_description ');
        $statement->bindValue(':host_id', (int) $host_id, PDO::PARAM_INT);
        $statement->bindValue(':service_description', "'%" . $search . "%'", PDO::PARAM_STR);
        $statement->execute();
    } else {
        $statement = $pearDB->prepare('SELECT service_id, service_description '
            . 'FROM service, host_service_relation hsr '
            . 'WHERE hsr.host_host_id = :host_id AND hsr.service_service_id = service_id');
        $statement->bindValue(':host_id', (int) $host_id, PDO::PARAM_INT);
        $statement->execute();
    }
    while ($elem = $statement->fetchRow()) {
        $hSvs[$elem['service_id']] = html_entity_decode(db2str($elem['service_description']), ENT_QUOTES, 'UTF-8');
    }
    $statement->closeCursor();

    // Get Services attached to hostgroups
    $statement1 = $pearDB->prepare('SELECT service_id, service_description '
        . 'FROM hostgroup_relation hgr, service, host_service_relation hsr'
        . ' WHERE hgr.host_host_id = :host_host_id'
        . ' AND hsr.hostgroup_hg_id = hgr.hostgroup_hg_id'
        . ' AND service_id = hsr.service_service_id');
    $statement1->bindValue(':host_host_id', (int) $host_id, PDO::PARAM_INT);
    $statement1->execute();
    while ($elem = $statement1->fetchRow()) {
        $hSvs[$elem['service_id']] = html_entity_decode(db2str($elem['service_description']), ENT_QUOTES, 'UTF-8');
    }
    $statement1->closeCursor();
    asort($hSvs);

    return $hSvs;
}

function getMyHostServicesByName($host_id = null)
{
    if (! $host_id) {
        return;
    }
    global $pearDB;
    $hSvs = [];
    $statement = $pearDB->prepare('SELECT service_id, service_description FROM service, host_service_relation hsr '
        . 'WHERE hsr.host_host_id =  :host_host_id '
        . 'AND hsr.service_service_id = service_id');
    $statement->bindValue(':host_host_id', (int) $host_id, PDO::PARAM_INT);
    $statement->execute();
    while ($elem = $statement->fetchRow()) {
        $hSvs[db2str($elem['service_description'])] = html_entity_decode($elem['service_id'], ENT_QUOTES, 'UTF-8');
    }
    $statement->closeCursor();
    $statement = $pearDB->prepare('SELECT service_id, service_description '
        . 'FROM hostgroup_relation hgr, service, host_service_relation hsr'
        . ' WHERE hgr.host_host_id = :host_host_id '
        . ' AND hsr.hostgroup_hg_id = hgr.hostgroup_hg_id'
        . ' AND service_id = hsr.service_service_id');
    $statement->bindValue(':host_host_id', (int) $host_id, PDO::PARAM_INT);
    $statement->execute();

    while ($elem = $statement->fetchRow()) {
        $hSvs[db2str($elem['service_description'])] = html_entity_decode($elem['service_id'], ENT_QUOTES, 'UTF-8');
    }
    $statement->closeCursor();

    return $hSvs;
}

function getMyServiceHosts($service_id = null)
{
    if (! $service_id) {
        return;
    }
    global $pearDB;
    $hosts = [];
    $statement = $pearDB->prepare('SELECT DISTINCT host_host_id FROM host_service_relation hsr '
        . 'WHERE hsr.service_service_id = :service_service_id ');
    $statement->bindValue(':service_service_id', (int) $service_id, PDO::PARAM_INT);
    $statement->execute();

    while ($elem = $statement->fetchRow()) {
        if ($elem['host_host_id']) {
            $hosts[$elem['host_host_id']] = $elem['host_host_id'];
        }
    }
    $statement->closeCursor();

    return $hosts;
}

function getMyServiceHostGroups($service_id = null)
{
    if (! $service_id) {
        return;
    }
    global $pearDB;
    $hgs = [];
    $statement = $pearDB->prepare('SELECT DISTINCT hostgroup_hg_id FROM host_service_relation hsr '
        . 'WHERE hsr.service_service_id =  :service_service_id ');
    $statement->bindValue(':service_service_id', (int) $service_id, PDO::PARAM_INT);
    $statement->execute();

    while ($elem = $statement->fetchRow()) {
        if ($elem['hostgroup_hg_id']) {
            $hgs[$elem['hostgroup_hg_id']] = $elem['hostgroup_hg_id'];
        }
    }
    $statement->closeCursor();

    return $hgs;
}

function getMyServiceTPLID($service_description = null)
{
    if (! $service_description) {
        return;
    }
    global $pearDB;
    $statement = $pearDB->prepare('SELECT service_id FROM service '
        . "WHERE service_description = :srv_desc AND service_register = '0' LIMIT 1");
    $statement->bindValue(':srv_desc', htmlentities(str2db($service_description), ENT_QUOTES, 'UTF-8'));
    $statement->execute();
    $row = $statement->fetchRow();
    if ($row['service_id']) {
        return $row['service_id'];
    }

    return null;
}

function getMyServiceTemplateModels($service_id = null)
{
    if (! $service_id) {
        return;
    }
    global $pearDB;
    $tplArr = [];
    while (1) {
        $statement = $pearDB->prepare('SELECT service_description, service_template_model_stm_id FROM service '
            . 'WHERE service_id = :service_id LIMIT 1');
        $statement->bindValue(':service_id', (int) $service_id, PDO::PARAM_INT);
        $statement->execute();

        $row = $statement->fetchRow();
        if ($row['service_description']) {
            $tplArr[$service_id] = html_entity_decode(db2str($row['service_description']), ENT_QUOTES, 'UTF-8');
        } else {
            break;
        }
        if ($row['service_template_model_stm_id']) {
            if (isset($tplArr[$row['service_template_model_stm_id']])) {
                break;
            }
            $service_id = $row['service_template_model_stm_id'];
        } else {
            break;
        }
    }

    return $tplArr;
}

//
// # COMMAND

function getMyCheckCmdName($service_id = null)
{
    if (! $service_id) {
        return;
    }
    global $pearDB;

    $tab = [];

    $query = 'SELECT command_name FROM command WHERE command_id = :command_id LIMIT 1';
    $statement = $pearDB->prepare($query);
    while (1) {
        $statement2 = $pearDB->prepare('SELECT command_command_id, service_template_model_stm_id FROM service '
            . 'WHERE service_id = :service_id LIMIT 1');
        $statement2->bindValue(':service_id', (int) $service_id, PDO::PARAM_INT);
        $statement2->execute();
        $row = $statement2->fetchRow();
        if ($row['command_command_id']) {
            $statement->bindValue(':command_id', (int) $row['command_command_id'], PDO::PARAM_INT);
            $statement->execute();
            $row2 = $statement->fetch(PDO::FETCH_ASSOC);

            return $row2['command_name'];
        }
        if ($row['service_template_model_stm_id']) {
            if (isset($tab[$row['service_template_model_stm_id']])) {
                break;
            }
            $service_id = $row['service_template_model_stm_id'];
            $tab[$service_id] = 1;
        } else {
            return null;
        }
    }

    return null;
}

function getMyCheckCmdArg($service_id = null)
{
    if (! $service_id) {
        return;
    }
    global $pearDB;
    $tab = [];

    while (1) {
        $query = 'SELECT command_command_id_arg, service_template_model_stm_id FROM service '
            . 'WHERE service_id = :service_id LIMIT 1';
        $statement = $pearDB->prepare($query);
        $statement->bindValue(':service_id', (int) $service_id, PDO::PARAM_INT);
        $statement->execute();
        $row = $statement->fetchRow();
        if ($row['command_command_id_arg']) {
            return db2str($row['command_command_id_arg']);
        }
        if ($row['service_template_model_stm_id']) {
            if (isset($tab[$row['service_template_model_stm_id']])) {
                break;
            }
            $service_id = $row['service_template_model_stm_id'];
            $tab[$service_id] = 1;
        } else {
            return null;
        }
    }

    return null;
}

/**
 * @param $service_id
 * @param null|mixed $host_name
 * @return unknown_type
 */
//
// # Upload conf needs

function getMyHostID($host_name = null)
{
    if (! $host_name) {
        return;
    }
    global $pearDB;
    $statement = $pearDB->prepare('SELECT host_id FROM host WHERE host_name = :host_name '
        . 'OR host_name = :ut8_encoded_host_name LIMIT 1');
    $statement->bindValue(':ut8_encoded_host_name', mb_convert_encoding($host_name, 'UTF-8', 'ISO-8859-1'), PDO::PARAM_STR);
    $statement->bindValue('host_name', $host_name, PDO::PARAM_STR);
    $statement->execute();
    if ($statement->rowCount()) {
        $row = $statement->fetchRow();

        return $row['host_id'];
    }

    return null;
}

//
// # GRAPHS

// Nagios Images

function return_image_list($mode = 0, $rep = null, $full = true, $origin_path = null)
{
    global $pearDB;

    $images = [];

    if ($full) {
        $images = [null => null];
    }

    $is_not_an_image = ['.', '..', 'README', 'readme', 'LICENCE', 'licence'];
    $is_a_valid_image = [0 => ['png' => 'png'], 1 => ['gif' => 'gif', 'png' => 'png', 'jpg' => 'jpg'], 2 => ['gif' => 'gif', 'png' => 'png', 'jpg' => 'jpg', 'gd2' => 'gd2']];

    $query = 'SELECT img_id, img_name, img_path, dir_name FROM view_img_dir, view_img, view_img_dir_relation vidr '
        . 'WHERE img_id = vidr.img_img_id AND dir_id = vidr.dir_dir_parent_id ORDER BY dir_name, img_name';
    $DBRESULT = $pearDB->query($query);
    $dir_name = null;
    $dir_name2 = null;
    $cpt = 1;
    while ($elem = $DBRESULT->fetchRow()) {
        $dir_name = $elem['dir_name'];
        if ($dir_name2 != $dir_name) {
            $dir_name2 = $dir_name;
            $images['REP_' . $cpt] = $dir_name;
            $cpt++;
        }
        $ext = null;
        $pinfo = pathinfo($elem['img_path']);
        if (isset($pinfo['extension'], $is_a_valid_image[$mode][$pinfo['extension']])) {
            $ext = '&nbsp;(' . $pinfo['extension'] . ')';
        }
        $images[$elem['img_id']] = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'
            . html_entity_decode($elem['img_name'], ENT_NOQUOTES) . $ext;
    }

    return $images;
}

function getLangs()
{
    $langs = ['browser' => _('Detection by browser')];
    $chemintotal = './locale/';

    if (is_dir($chemintotal)) {
        if ($handle = opendir($chemintotal)) {
            while ($file = readdir($handle)) {
                if (is_dir("{$chemintotal}/{$file}") && strcmp($file, '.') && strcmp($file, '..')) {
                    $langTitle = str_replace('.UTF-8', '', $file);
                    $langs[$file] = $langTitle;
                }
            }
            closedir($handle);
        }
    }
    if (! array_key_exists('en_US.UTF-8', $langs)) {
        $langs['en_US.UTF-8'] = 'en_US';
    }

    return $langs;
}

function service_has_graph($host, $service, $dbo = null)
{
    global $pearDBO;
    if (is_null($dbo)) {
        $dbo = $pearDBO;
    }
    if (is_numeric($host) && is_numeric($service)) {
        $statement = $pearDBO->prepare('SELECT i.* FROM index_data i, metrics m WHERE i.id = m.index_id '
            . 'AND i.host_id = :host_id  AND i.service_id = :service_id');
        $statement->bindValue(':host_id', (int) $host, PDO::PARAM_INT);
        $statement->bindValue(':service_id', (int) $service, PDO::PARAM_INT);
        $statement->execute();

        if ($statement->rowCount() > 0) {
            return true;
        }
    }
    if (! is_numeric($host) && ! is_numeric($service)) {
        $statement = $pearDBO->prepare('SELECT i.* FROM index_data i, metrics m WHERE i.id = m.index_id '
            . 'AND i.host_name = :host_name AND i.service_description = :service_description');
        $statement->bindValue(':host_name', $host, PDO::PARAM_STR);
        $statement->bindValue(':service_description', $service, PDO::PARAM_STR);
        $statement->execute();

        if ($statement->rowCount() > 0) {
            return true;
        }
    }

    return false;
}

/**
 * Send a well formatted error.
 *
 * @param string $message Message to send
 * @param int $code HTTP error code
 * @param string $type Response type (json by default)
 */
function sendError(string $message, int $code = 500, string $type = 'json')
{
    switch ($type) {
        case 'xml':
            header('Content-Type: text/xml');
            echo '<message>' . $message . '</message>';
            break;
        case 'json':
        default:
            header('Content-Type: application/json');
            echo json_encode(['message' => $message]);
            break;
    }
    switch ($code) {
        case 401:
            header('HTTP/1.0 401 Unauthorized');
            break;
        case 500:
        default:
            header('HTTP/1.0 500 Internal Server Error');
    }

    exit();
}

// Ajax tests

function get_error($motif)
{
    $buffer = null;
    $buffer .= '<reponse>';
    $buffer .= $motif;
    $buffer .= '</reponse>';
    header('Content-Type: text/xml');
    echo $buffer;

    exit(0);
}

// End Ajax Test
function GetMyHostPoller($pearDB, $host_name = null)
{
    if (! isset($host_name)) {
        return 0;
    }
    $statement = $pearDB->prepare('SELECT `id` FROM nagios_server, ns_host_relation, host '
       . 'WHERE host.host_name = :host_name AND host.host_id = ns_host_relation.host_host_id '
       . 'AND ns_host_relation.nagios_server_id = nagios_server.id LIMIT 1');
    $statement->bindValue(':host_name', $host_name, PDO::PARAM_STR);
    $statement->execute();

    $nagios_server = $statement->fetchRow();
    if (isset($nagios_server['id'])) {
        return $nagios_server['id'];
    }
    $sql = "SELECT id FROM nagios_server WHERE localhost = '1' LIMIT 1";
    $res = $pearDB->query($sql);
    if ($res->rowCount()) {
        $row = $res->fetchRow();

        return $row['id'];
    }

    return 0;
}

function check_session($sid, $pearDB)
{
    if (isset($sid)) {
        $statement = $pearDB->prepare('SELECT * FROM session WHERE session_id = :sid');
        $statement->bindValue(':sid', htmlentities($sid, ENT_QUOTES, 'UTF-8'));
        $statement->execute();
        if ($session = $statement->fetchRow()) {
            return $session['user_id'];
        }
        get_error('bad session id');

    } else {
        get_error('need session identifiant !');
    }

    return 0;
}

function db2str($string)
{
    $string = str_replace('#BR#', '\\n', $string ?? '');
    $string = str_replace('#T#', '\\t', $string);
    $string = str_replace('#R#', '\\r', $string);
    $string = str_replace('#S#', '/', $string);

    return str_replace('#BS#', '\\', $string);
}

function str2db($string)
{
    /* $string = str_replace("\\n", '#BR#', $string);
      $string = str_replace("\\t", '#T#', $string);
      $string = str_replace("\\r", '#R#', $string);
      $string = str_replace("/", '#S#', $string);
      $string = str_replace("\\", '#BS#', $string); */
    return $string;
}

/**
 * Return the list of template
 *
 * @param int $svcId The service ID
 * @param mixed $pearDB
 * @param mixed $alreadyProcessed
 * @return array
 */
function getListTemplates($pearDB, $svcId, $alreadyProcessed = [])
{
    $svcTmpl = [];
    if (in_array($svcId, $alreadyProcessed)) {
        return $svcTmpl;
    }
    $alreadyProcessed[] = $svcId;
    $statement = $pearDB->prepare('SELECT * FROM service WHERE service_id = :service_id');
    $statement->bindValue(':service_id', (int) $svcId, PDO::PARAM_INT);
    $statement->execute();

    if ($row = $statement->fetch()) {
        if ($row['service_template_model_stm_id'] !== null) {
            $svcTmpl = array_merge(
                $svcTmpl,
                getListTemplates($pearDB, $row['service_template_model_stm_id'], $alreadyProcessed)
            );
        }
        $svcTmpl[] = $row;
    }

    return $svcTmpl;
}

if (! function_exists('array_column')) {
    function array_column($array, $column_name)
    {
        return array_map(function ($element) use ($column_name) {
            return $element[$column_name];
        }, $array);
    }

}

// Global Function

/**
 * get first menu entry allowed to a given user
 *
 * @param string $lcaTStr Allowed topology pages separated by comma
 * @param int $defaultPage User default page
 * @return array The topology information (url, options, name...)
 */
function getFirstAllowedMenu($lcaTStr, $defaultPage)
{
    global $pearDB;

    $defaultPageOptions = null;

    // manage default page with option (eg: 50110&o=general)
    if (preg_match('/(\d+)(\D+)/', $defaultPage, $matches)) {
        $defaultPage = $matches[1];
        $defaultPageOptions = $matches[2];
    }

    $statement = $pearDB->prepare(
        'SELECT topology_parent,topology_name,topology_id,topology_url,topology_page,topology_url_opt, is_react '
        . 'FROM topology '
        . 'WHERE ' . (trim($lcaTStr) != '' ? "topology_page IN ({$lcaTStr}) AND " : '')
        . "topology_page IS NOT NULL AND topology_show = '1' AND topology_url IS NOT NULL "
        . 'ORDER BY FIELD(topology_page, :default_page) DESC, '
        . 'FIELD(topology_url_opt, :default_page_options) DESC, '
        . 'topology_page ASC, topology_id ASC '
        . 'LIMIT 1'
    );

    $statement->bindValue(':default_page', (int) $defaultPage, PDO::PARAM_INT);
    $statement->bindValue(':default_page_options', $defaultPageOptions, PDO::PARAM_STR);

    $statement->execute();

    if (! $statement->rowCount()) {
        return [];
    }

    return $statement->fetch();
}

function reset_search_page($url)
{
    // Clean Vars
    global $centreon;
    if (! isset($url)) {
        return;
    }
    if (
        isset($_GET['search'], $centreon->historySearch[$url])

        && $_GET['search'] != $centreon->historySearch[$url]
        && ! isset($_GET['num'])
        && ! isset($_POST['num'])
    ) {
        $_POST['num'] = 0;
        $_GET['num'] = 0;
    } elseif (
        isset($_GET['search'], $_POST['search'])

        && $_GET['search'] === $_POST['search']
    ) {
        // if the user change the search filter, we reset the num argument sent in the hybride POST and GET request
        $_POST['num'] = $_GET['num'] = 0;
    }
}

/**
 * Return an array of flag names which are enabled (active).
 *
 * @return array<string>
 *
 * @see \Core\Common\Infrastructure\FeatureFlags::getEnabled()
 */
function get_enabled_feature_flags(): array
{
    static $enabledFlags;
    if (isset($enabledFlags)) {
        return $enabledFlags;
    }

    $service = App\Kernel::createForWeb()->getContainer()->get(Core\Common\Infrastructure\FeatureFlags::class);

    return $enabledFlags = ($service instanceof Core\Common\Infrastructure\FeatureFlags ? $service->getEnabled() : []);
}

/**
 * Indicates whether the platform is Cloud-based or not.
 *
 * @return bool
 */
function isCloudPlatform(): bool
{
    static $isCloudPlatform;
    if (isset($isCloudPlatform)) {
        return $isCloudPlatform;
    }
    $service = App\Kernel::createForWeb()->getContainer()->get(Core\Common\Infrastructure\FeatureFlags::class);

    return $isCloudPlatform = ($service instanceof Core\Common\Infrastructure\FeatureFlags ? $service->isCloudPlatform() : false);
}

/**
 * We consider an empty feature **in the legacy code** as enabled.
 * We tolerate this nonsense for the legacy : KISS.
 */
function is_enabled_feature_flag(?string $feature): bool
{
    return $feature === null || $feature === ''
        || in_array($feature, get_enabled_feature_flags(), true);
}

function get_child($id_page, $lcaTStr)
{
    global $pearDB;

    if ($lcaTStr != '') {
        $rq = <<<SQL
            SELECT topology_parent, topology_name, topology_id, topology_url, topology_url_substitute,
                topology_page, topology_url_opt, is_react, topology_feature_flag
            FROM topology
            WHERE topology_page IN ({$lcaTStr})
                AND topology_parent = :id_page
                AND topology_page IS NOT NULL
                AND topology_show = '1'
            ORDER BY topology_order, topology_group
            SQL;
    } else {
        $rq = <<<'SQL'
            SELECT topology_parent, topology_name, topology_id, topology_url, topology_url_substitute,
                topology_page, topology_url_opt, is_react, topology_feature_flag
            FROM topology
            WHERE topology_parent = :id_page
              AND topology_page IS NOT NULL
              AND topology_show = '1'
            ORDER BY topology_order, topology_group
            SQL;
    }
    $statement = $pearDB->prepare($rq);
    $statement->bindValue(':id_page', (int) $id_page, PDO::PARAM_INT);
    $statement->execute();
    $redirect = $statement->fetch(PDO::FETCH_ASSOC);
    if (! is_enabled_feature_flag($redirect['topology_feature_flag'] ?? null)) {
        return false;
    }

    return $redirect;
}

/**
 * Quickform rule that validate geo_coords
 *
 * @throws HTML_QuickForm_Error
 * @return bool
 */
function validateGeoCoords()
{
    global $form;
    $coords = $form->getElementValue('geo_coords');

    return (bool) (
        preg_match(
            '/^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/',
            $coords
        )
    );
}

function truncateGeoCoords(): string
{
    global $form;
    $coords = trim($form->getElementValue('geo_coords'));

    $parts = explode(',', $coords);
    if (count($parts) !== 2) {
        return $coords;
    }

    $latitude = truncateDecimals($parts[0]);
    $longitude = truncateDecimals($parts[1]);

    return sprintf('%s,%s', $latitude, $longitude);
}

function truncateDecimals(string $value): string
{
    if (! str_contains($value, '.')) {
        return $value;
    }

    [$intPart, $decimalPart] = explode('.', $value, 2);
    $decimalPart = mb_substr($decimalPart, 0, 6);

    return $intPart . '.' . $decimalPart;
}

/**
 * Get the select option.
 *
 * @return array<int, int>
 */
function getSelectOption()
{
    $stringToArray = function (string $value): array {
        if (str_contains($value, ',')) {
            $value = explode(',', rtrim($value, ','));

            return array_flip($value);
        }

        return [$value => '1'];
    };
    if (isset($_GET['select'])) {
        return is_array($_GET['select'])
            ? $_GET['select']
            : $stringToArray($_GET['select']);
    }
    if (isset($_POST['select'])) {
        return is_array($_POST['select'])
            ? $_POST['select']
            : $stringToArray($_POST['select']);
    }

    return [];
}

/**
 * Get the duplicate number option.
 *
 * @return array<int, int>
 */
function getDuplicateNumberOption()
{
    if (isset($_GET['dupNbr'])) {
        return is_array($_GET['dupNbr'])
            ? $_GET['dupNbr']
            : [];
    }
    if (isset($_POST['dupNbr'])) {
        return is_array($_POST['dupNbr'])
            ? $_POST['dupNbr']
            : [];
    }

    return [];
}

function isNotEmptyAfterStringSanitize($test): bool
{
    return ! (empty(HtmlAnalyzer::sanitizeAndRemoveTags($test)));
}

/**
 * Create a CSRF token
 *
 * @return string
 */
function createCSRFToken(): string
{
    $token = bin2hex(openssl_random_pseudo_bytes(16));

    if (! isset($_SESSION['x-centreon-token']) || ! is_array($_SESSION['x-centreon-token'])) {
        $_SESSION['x-centreon-token'] = [];
        $_SESSION['x-centreon-token-generated-at'] = [];
    }

    $_SESSION['x-centreon-token'][] = $token;
    $_SESSION['x-centreon-token-generated-at'][(string) $token] = time();

    return $token;
}

/**
 * Remove CSRF tokens older than 15min form session
 */
function purgeOutdatedCSRFTokens()
{
    foreach ($_SESSION['x-centreon-token-generated-at'] as $key => $value) {
        $elapsedTime = time() - $value;

        if ($elapsedTime > (15 * 60)) {
            $tokenKey = array_search((string) $key, $_SESSION['x-centreon-token']);
            unset($_SESSION['x-centreon-token'][$tokenKey], $_SESSION['x-centreon-token-generated-at'][(string) $key]);

        }
    }
}

/**
 * Remove CSRF Token from session
 */
function purgeCSRFToken()
{
    $token = $_POST['centreon_token'] ?? $_GET['centreon_token'] ?? null;

    $key = array_search((string) $token, $_SESSION['x-centreon-token']);
    unset($_SESSION['x-centreon-token'][$key], $_SESSION['x-centreon-token-generated-at'][(string) $token]);

}

/**
 * Check CRSF token validity
 *
 * @return bool
 */
function isCSRFTokenValid()
{
    $isValid = false;

    $token = $_POST['centreon_token'] ?? $_GET['centreon_token'] ?? null;
    if ($token !== null && in_array($token, $_SESSION['x-centreon-token'])) {
        $isValid = true;
    }

    return $isValid;
}

/**
 * Display error message for unvalid form (CSRF token unvalid or too old)
 */
function unvalidFormMessage()
{
    echo "<div class='msg' align='center'>"
        . _('The form has not been submitted since 15 minutes. Please retry to resubmit')
        . '</div>';
}

/**
 * Return ids of hosts linked to hostgroups
 *
 * @param int[] $hostgroupIds
 * @param bool $shouldHostgroupBeEnabled (default true)
 * @throws Exception
 * @return int[]
 */
function findHostsForConfigChangeFlagFromHostGroupIds(array $hostgroupIds, bool $shouldHostgroupBeEnabled = true): array
{
    if ($hostgroupIds === []) {
        return [];
    }

    global $pearDB;

    $bindedParams = [];
    $hostgroupIds = array_values($hostgroupIds);
    foreach ($hostgroupIds as $key => $hostgroupId) {
        $bindedParams[':hostgroup_id_' . $key] = $hostgroupId;
    }

    if ($shouldHostgroupBeEnabled) {
        $query = "SELECT DISTINCT(hgr.host_host_id)
            FROM hostgroup_relation hgr
            JOIN hostgroup ON hostgroup.hg_id = hgr.hostgroup_hg_id
            WHERE hostgroup.hg_activate = '1'
            AND hgr.hostgroup_hg_id IN (" . implode(', ', array_keys($bindedParams)) . ')';
    } else {
        $query = 'SELECT DISTINCT(hgr.host_host_id) FROM hostgroup_relation hgr
            WHERE hgr.hostgroup_hg_id IN (' . implode(', ', array_keys($bindedParams)) . ')';
    }

    $stmt = $pearDB->prepare($query);
    foreach ($bindedParams as $bindedParam => $bindedValue) {
        $stmt->bindValue($bindedParam, $bindedValue, PDO::PARAM_INT);
    }
    $stmt->execute();

    return $stmt->fetchAll(PDO::FETCH_COLUMN);
}

/**
 * Return ids of hosts linked to services
 *
 * @param int[] $serviceIds
 * @param bool $shouldServiceBeEnabled (default true)
 * @throws Exception
 * @return int[]
 */
function findHostsForConfigChangeFlagFromServiceIds(array $serviceIds, bool $shoudlServiceBeEnabled = true): array
{
    if ($serviceIds === []) {
        return [];
    }

    global $pearDB;

    $bindedParams = [];
    $serviceIds = array_values($serviceIds);
    foreach ($serviceIds as $key => $serviceId) {
        $bindedParams[':service_id_' . $key] = $serviceId;
    }

    if ($shoudlServiceBeEnabled) {
        $query = "SELECT DISTINCT(hsr.host_host_id)
            FROM host_service_relation hsr
            JOIN service ON service.service_id = hsr.service_service_id
            WHERE service.service_activate = '1' AND hsr.service_service_id IN ("
            . implode(', ', array_keys($bindedParams)) . ')';
    } else {
        $query = 'SELECT DISTINCT(hsr.host_host_id)
            FROM host_service_relation hsr
            WHERE hsr.service_service_id IN (' . implode(', ', array_keys($bindedParams)) . ')';
    }

    $stmt = $pearDB->prepare($query);
    foreach ($bindedParams as $bindedParam => $bindedValue) {
        $stmt->bindValue($bindedParam, $bindedValue, PDO::PARAM_INT);
    }
    $stmt->execute();

    return $stmt->fetchAll(PDO::FETCH_COLUMN);
}

/**
 * Return ids of services linked to templates recursively
 *
 * @param int[] $serviceTemplateIds
 * @throws Exception
 * @return int[]
 */
function findServicesForConfigChangeFlagFromServiceTemplateIds(array $serviceTemplateIds): array
{
    if ($serviceTemplateIds === []) {
        return [];
    }

    global $pearDB;

    $bindedParams = [];
    $serviceTemplateIds = array_values($serviceTemplateIds);
    foreach ($serviceTemplateIds as $key => $serviceTemplateId) {
        $bindedParams[':servicetemplate_id_' . $key] = $serviceTemplateId;
    }

    $query = "SELECT service_id, service_register FROM service
        WHERE service.service_activate = '1'
        AND service_template_model_stm_id IN (" . implode(', ', array_keys($bindedParams)) . ')';

    $stmt = $pearDB->prepare($query);
    foreach ($bindedParams as $bindedParam => $bindedValue) {
        $stmt->bindValue($bindedParam, $bindedValue, PDO::PARAM_INT);
    }
    $stmt->execute();

    $serviceIds = [];
    $serviceTemplateIds2 = [];
    foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $value) {
        if ($value['service_register'] === '0') {
            $serviceTemplateIds2[] = $value['service_id'];
        } else {
            $serviceIds[] = $value['service_id'];
        }
    }

    return array_merge(
        $serviceIds,
        findServicesForConfigChangeFlagFromServiceTemplateIds($serviceTemplateIds2)
    );
}

/**
 * Return ids of hosts linked to service
 *
 * @param int $servicegroupId
 * @param bool $shouldServicegroupBeEnabled (default true)
 * @throws Exception
 * @return int[]
 */
function findHostsForConfigChangeFlagFromServiceGroupId(
    int $servicegroupId,
    bool $shouldServicegroupBeEnabled = true,
): array {
    global $pearDB;

    $query = "SELECT sgr.*, service.service_register
        FROM servicegroup_relation sgr
        JOIN servicegroup ON servicegroup.sg_id = sgr.servicegroup_sg_id
        JOIN service ON service.service_id = sgr.service_service_id
        WHERE service.service_activate = '1' AND sgr.servicegroup_sg_id = :servicegroup_id"
        . ($shouldServicegroupBeEnabled ? " AND servicegroup.sg_activate = '1'" : '');

    $stmt = $pearDB->prepare($query);
    $stmt->bindValue(':servicegroup_id', $servicegroupId, PDO::PARAM_INT);
    $stmt->execute();

    $hostIds = [];
    $hostgroupIds = [];
    $serviceTemplateIds = [];
    foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $value) {
        if ($value['service_register'] === '0') {
            $serviceTemplateIds[] = $value['service_service_id'];
        } elseif ($value['hostgroup_hg_id'] !== null) {
            $hostgroupIds[] = $value['hostgroup_hg_id'];
        } else {
            $hostIds[] = $value['host_host_id'];
        }
    }

    $serviceIds = findServicesForConfigChangeFlagFromServiceTemplateIds($serviceTemplateIds);

    return array_merge(
        $hostIds,
        findHostsForConfigChangeFlagFromHostGroupIds($hostgroupIds),
        findHostsForConfigChangeFlagFromServiceIds($serviceIds)
    );
}

/**
 * Return ids of pollers linked to hosts
 *
 * @param int[] $hostIds
 * @param bool $shouldHostBeEnabled (default true)
 * @throws Exception
 * @return int[]
 */
function findPollersForConfigChangeFlagFromHostIds(array $hostIds, bool $shouldHostBeEnabled = true): array
{
    if ($hostIds === []) {
        return [];
    }

    global $pearDB;

    $bindedParams = [];
    $hostIds = array_values($hostIds);
    foreach ($hostIds as $key => $hostId) {
        $bindedParams[':host_id_' . $key] = $hostId;
    }

    if ($shouldHostBeEnabled) {
        $query = "SELECT DISTINCT(phr.nagios_server_id)
        FROM ns_host_relation phr
        JOIN host ON host.host_id = phr.host_host_id
        WHERE host.host_activate = '1' AND phr.host_host_id IN (" . implode(', ', array_keys($bindedParams)) . ')';
    } else {
        $query = 'SELECT DISTINCT(phr.nagios_server_id) FROM ns_host_relation phr
           WHERE phr.host_host_id IN (' . implode(', ', array_keys($bindedParams)) . ')';
    }

    $stmt = $pearDB->prepare($query);
    foreach ($bindedParams as $bindedParam => $bindedValue) {
        $stmt->bindValue($bindedParam, $bindedValue, PDO::PARAM_INT);
    }
    $stmt->execute();

    return $stmt->fetchAll(PDO::FETCH_COLUMN);
}

/**
 * Set 'updated' flag to '1' for all listed poller ids
 *
 * @param int[] $pollerIds
 * @throws Exception
 */
function definePollersToUpdated(array $pollerIds): void
{
    if ($pollerIds === []) {
        return;
    }

    global $pearDB;

    $bindedParams = [];
    $pollerIds = array_values($pollerIds);
    foreach ($pollerIds as $key => $pollerId) {
        $bindedParams[':poller_id_' . $key] = $pollerId;
    }
    $query = "UPDATE nagios_server SET updated = '1' WHERE id IN (" . implode(', ', array_keys($bindedParams)) . ')';
    $stmt = $pearDB->prepare($query);
    foreach ($bindedParams as $bindedParam => $bindedValue) {
        $stmt->bindValue($bindedParam, $bindedValue, PDO::PARAM_INT);
    }
    $stmt->execute();
}

/**
 * Get current Centreon version
 * @param mixed $pearDB
 */
function getCentreonVersion($pearDB)
{
    $query = 'SELECT `value` FROM `informations` WHERE `key` = "version"';
    try {
        $res = $pearDB->query($query);
    } catch (PDOException $e) {
        return null;
    }
    $row = $res->fetchRow();

    return $row['value'];
}

/**
 * Set relevent pollers as updated
 *
 * @param string $resourceType
 * @param int $resourceId
 * @param int[] $previousPollers
 * @param bool $shouldResourceBeEnabled (default true)
 * @throws Exception
 */
function signalConfigurationChange(
    string $resourceType,
    int $resourceId,
    array $previousPollers = [],
    bool $shouldResourceBeEnabled = true,
): void {
    $hostIds = [];
    switch ($resourceType) {
        case 'host':
            $hostIds[] = $resourceId;
            break;
        case 'hostgroup':
            $hostIds = array_merge(
                $hostIds,
                findHostsForConfigChangeFlagFromHostGroupIds([$resourceId], $shouldResourceBeEnabled)
            );
            break;
        case 'service':
            $hostIds = array_merge(
                $hostIds,
                findHostsForConfigChangeFlagFromServiceIds([$resourceId], $shouldResourceBeEnabled)
            );
            break;
        case 'servicegroup':
            $hostIds = array_merge(
                $hostIds,
                findHostsForConfigChangeFlagFromServiceGroupId($resourceId, $shouldResourceBeEnabled)
            );
            break;
        default:
            throw new Exception('Unknown resource type:' . $resourceType);
            break;
    }
    $pollerIds = findPollersForConfigChangeFlagFromHostIds(
        $hostIds,
        $resourceType === 'host' ? $shouldResourceBeEnabled : true
    );

    definePollersToUpdated(array_merge($pollerIds, $previousPollers));
}
