<?php
/**
 * Ce script définit la classe 'opencimetiere'.
 *
 * @package opencimetiere
 * @version SVN : $Id$
 */

/**
 *
 */
if (file_exists("../dyn/locales.inc.php") === true) {
    require_once "../dyn/locales.inc.php";
}

/**
 * Définition de la constante représentant le chemin d'accès au framework
 */
define("PATH_OPENMAIRIE", getcwd()."/../core/");

/**
 * TCPDF specific config
 */
define("K_TCPDF_EXTERNAL_CONFIG", true);
define("K_TCPDF_CALLS_IN_HTML", true);

/**
 * Twig Cache path
 */
define("PATH_TWIG_CACHE", "../var/tmp/cache/");

/**
 * Dépendances PHP du framework
 * On modifie la valeur de la directive de configuration include_path en
 * fonction pour y ajouter les chemins vers les librairies dont le framework
 * dépend.
 */
set_include_path(
    get_include_path().PATH_SEPARATOR.implode(
        PATH_SEPARATOR,
        array(
            getcwd()."/../php/pear",
            getcwd()."/../php/db",
            getcwd()."/../php/fpdf",
            getcwd()."/../php/phpmailer",
            getcwd()."/../php/tcpdf",
        )
    )
);

/**
 *
 */
if (file_exists("../dyn/debug.inc.php") === true) {
    require_once "../dyn/debug.inc.php";
}

/**
 *
 */
(defined("PATH_OPENMAIRIE") ? "" : define("PATH_OPENMAIRIE", ""));

/**
 *
 */
require_once PATH_OPENMAIRIE."om_application.class.php";

/**
 * Surcharges du framework à réintégrer
 */
require_once "../obj/om_application_override.class.php";

/**
 * Définition de la classe 'opencimetiere' (om_application).
 *
 * Cette classe permet la surcharge de certaines méthodes de
 * la classe om_application pour des besoins spécifiques de l'application.
 */
class opencimetiere extends om_application_override {

    /**
     * Gestion du nom de l'application.
     *
     * @var mixed Configuration niveau application.
     */
    protected $_application_name = "openCimetière";

    /**
     * Titre HTML.
     *
     * @var mixed Configuration niveau application.
     */
    protected $html_head_title = ":: openMairie :: openCimetière";

    /**
     * Gestion du nom de la session.
     *
     * @var mixed Configuration niveau application.
     */
    protected $_session_name = "1bb484de79f96a6dab00aaf4463c18f8bf";

    /**
     * Gestion du mode de gestion des permissions.
     *
     * @var mixed Configuration niveau application.
     */
    protected $config__permission_by_hierarchical_profile = false;

    /**
     * Stockage des paramètres des collectivités.
     *
     * @var array
     */
    protected $collectivitiesParameters = array();

    /**
     *
     * @return void
     */
    function setDefaultValues() {
        $this->config['upload_extension'] = ".geojson;.gif;.jpg;.jpeg;.png;.txt;.pdf;.csv;";
        $this->addHTMLHeadCss(
            array(
                "../app/lib/gridjs/mermaid.min.css",
            ),
            22
        );
        $this->addHTMLHeadJs(
            array(
                "../app/lib/gridjs/gridjs.min.js",
            ),
            22
        );
        $this->setHTMLHeadCss(
            array(
               30 => array(
                    "../lib/leaflet/leaflet.css",
                    "../lib/leaflet/leaflet-sidebar.min.css",
                    "../lib/fontawesome/css/font-awesome.min.css",
                ),
                40 => array(
                    "../app/lib/remixicon/font/remixicon.css",
                    "../app/lib/inter-ui/inter.css",
                    "../app/css/style.css",
                ),
            ),
            true

        );
    }

    /**
     * Surcharge - getParameter().
     *
     * Force les paramètres suivants aux valeurs suivantes :
     * - is_settings_view_enabled = true
     *
     * @return mixed
     */
    function getParameter($param = null) {
        // openCimetière est fait pour fonctionner avec la view 'settings'
        // pour gérer le menu 'Administration & Paramétrage'. On force donc le
        // paramètre.
        if ($param == "is_settings_view_enabled") {
            return true;
        }
        return parent::getParameter($param);
    }

    /**
     * Retourne le nombre d'années avant que la réduction d'un défunt soit autorisée,
     * soit depuis le paramètre temps_reduction,
     * soit la valeur par défaut du logiciel : 5 (ans)
     *
     * @return integer nombre d'années
     */
    function get_parameter_temps_reduction(): int
    {
        $temps_reduction = $this->getParameter("temps_reduction");
        if (is_null($temps_reduction)) {
            return 5;
        }

        return (int) $temps_reduction;
    }

    /**
     * get_option_casse_force_majuscule
     *
     * Permet de recupérer les valeurs de l'option option_casse_force_majuscule.
     *
     * @return array
     */
    function get_option_casse_force_majuscule() {
        return $this->get_parametrer_with_multiple_values('option_casse_force_majuscule', "\n", '=');
    }

    /**
     * get_parametrer_with_multiple_values
     *
     * Permet de retourner un tableau contenant plusieurs valeur pour une option
     *
     * @param $option_libelle Le nom de l'option que l'on veut récupérer
     * @param $separator Le séparateur de chaque valeur de l'option (par défaut c'est un saut de ligne "\n")
     * @param $value_separator Si il y a un indicateur dans la valeur (exemple defunt.nom=true le séparateur est =)
     * par défaut à null
     *
     * @return array
     */
    function get_parametrer_with_multiple_values($option_libelle, $separator = "\n", $value_separator = null) {
        $param_tab = array();
        if (! empty($this->getParameter($option_libelle))) {
            foreach (explode($separator, $this->getParameter($option_libelle)) as $option_value) {
                if ($value_separator != null) {
                    $option_value_exploded = explode($value_separator, $option_value);
                    if (is_array($option_value_exploded)) {
                        $param_tab[$option_value_exploded[0]] = trim($option_value_exploded[1]) == 'true' ? true : false;
                    }
                } else {
                    $param_tab[] = $option_value;
                }
            }
        }
        return $param_tab;
    }

    /**
     * Surcharge - view_main().
     *
     * Ajoute la vue 'search' comme un nouveau module.
     *
     * @return void
     */
    function view_main() {
        if ($this->get_submitted_get_value("module") === "search") {
            $this->view_module_search();
            return;
        }
        parent::view_main();
    }

    /**
     * Cette vue permet d'afficher un formulaire de recherche globale ainsi que
     * les résultats de recherche associés.
     *
     * @return void
     */
    function view_module_search() {
        $this->isAuthorized("recherche");
        $this->setTitle(__("recherche")." -> ".__("recherche globale"));
        $this->setFlag(null);
        $this->display();
        //
        set_time_limit(1800);
        //
        (isset($_GET['obj']) ? $obj = $_GET['obj'] : $obj = "");
        // Description de la page
        $description = __("Cette page vous permet de rechercher dans toutes les tables ".
        "de l'application.");
        $this->displayDescription($description);
        //
        echo "\n<div id=\"edition\">\n";
        //
        echo "<fieldset class=\"cadre ui-corner-all ui-widget-content\">\n";
        echo "\t<legend class=\"ui-corner-all ui-widget-content ui-state-active\">";
        echo __("recherche");
        echo "</legend>\n";
        //
        require_once "../sql/".OM_DB_PHPTYPE."/".$obj.".search.inc.php";
        require_once "../obj/search.class.php";
        $objRech = new search($this, $configTypeRecherche);
        $objRech->searchInclude("../app/index.php?module=search&obj=concession");
        $objRech->showForm();
        $objRech->showResults();
        //
        echo "</fieldset>\n";
        //
        echo "</div>";
    }

    /**
     * SURCHARGE DE LA CLASSE OM_APPLICATION.
     *
     * @see Documentation sur la méthode parent 'om_application:getCollectivite'.
     */
    function getCollectivite($om_collectivite_idx = null) {
        // On vérifie si une valeur a été passée en paramètre ou non.
        if ($om_collectivite_idx === null) {
            // Cas d'utilisation n°1 : nous sommes dans le cas où on
            // veut récupérer les informations de la collectivité de
            // l'utilisateur et on stocke l'info dans un flag.
            $is_get_collectivite_from_user = true;
            // On initialise l'identifiant de la collectivité
            // à partir de la variable de session de l'utilisateur.
            $om_collectivite_idx = $_SESSION['collectivite'];
        } else {
            // Cas d'utilisation n°2 : nous sommes dans le cas où on
            // veut récupérer les informations de la collectivité
            // passée en paramètre et on stocke l'info dans le flag.
            $is_get_collectivite_from_user = false;
        }


        if (array_key_exists($om_collectivite_idx, $this->collectivitiesParameters) === false
            || empty($this->collectivitiesParameters[$om_collectivite_idx]) === true) {
            $collectivite_parameters = parent::getCollectivite($om_collectivite_idx);

            //// BEGIN - SURCHARGE OPENADS

            // Ajout du paramétrage du sig pour la collectivité
            if (file_exists("../dyn/var.inc")) {
                include "../dyn/var.inc";
            }
            if (file_exists("../dyn/sig.inc.php")) {
                include "../dyn/sig.inc.php";
            }
            if (!isset($sig_externe)) {
                $sig_externe = "sig-default";
            }
            $idx_multi = $this->get_idx_collectivite_multi();

            if (isset($collectivite_parameters['om_collectivite_idx'])
                && isset($conf[$sig_externe][$collectivite_parameters['om_collectivite_idx']])
                && isset($conf[$sig_externe]["sig_treatment_mod"])
                && isset($collectivite_parameters["option_localisation"])
                && $collectivite_parameters["option_localisation"] == "sig_externe") {
                // Cas numéro 1 : conf sig définie sur la collectivité et option sig active
                $collectivite_parameters["sig"] = $conf[$sig_externe][$collectivite_parameters['om_collectivite_idx']];
                $collectivite_parameters["sig"]["sig_treatment_mod"] = $conf[$sig_externe]["sig_treatment_mod"];
            } elseif ($idx_multi != ''
                && isset($conf[$sig_externe][$idx_multi])
                && isset($conf[$sig_externe]["sig_treatment_mod"])
                && isset($collectivite_parameters["option_localisation"])
                && $collectivite_parameters["option_localisation"] == "sig_externe") {
                // Cas numéro : conf sig définie sur la collectivité multi et option_sig activé pour la collectivité mono
                $collectivite_parameters["sig"] = $conf[$sig_externe][$idx_multi];
                $collectivite_parameters["sig"]["sig_treatment_mod"] = $conf[$sig_externe]["sig_treatment_mod"];
            }

            //// END - SURCHARGE OPENADS

            // Si on se trouve dans le cas d'utilisation n°1
            if ($is_get_collectivite_from_user === true) {
                // Alors on stocke dans l'attribut collectivite le tableau de
                // paramètres pour utilisation depuis la méthode 'getParameter'.
                $this->collectivite = $collectivite_parameters;
            }
            // On stocke le tableau de paramètres.
            $this->collectivitiesParameters[$om_collectivite_idx] = $collectivite_parameters;
        }
        // Renvoie la liste des paramètres de la collectivité voulue
        return $this->collectivitiesParameters[$om_collectivite_idx];
    }

    /**
     * Récupère toutes les collectivités ayant le niveau passé en
     * paramètre. Si le niveau n'est pas donné ou que ce n'est pas
     * un nombre renvoi une chaine vide.
     *
     * @param integer niveau de la collectivite
     * @return string
     */
    public function get_collectivite_par_niveau($niveau) {
        if (empty($niveau) || ! is_numeric($niveau)) {
            return '';
        }
        $qres = $this->get_one_result_from_db_query(
            sprintf(
                'SELECT
                    om_collectivite
                FROM
                    %1$som_collectivite
                WHERE
                    niveau = \'%2$d\'',
                DB_PREFIXE,
                intval($niveau)
            ),
            array('force_return' => false, 'origin' => __METHOD__)
        );
        return $qres['result'];
    }

    /**
     * Retourne l'identifiant de la collectivité multi ou l'identifiant de la
     * seule collectivité dans le cas d'une installation mono.
     *
     * @return integer Identifiant de la collectivité multi.
     */
    public function get_idx_collectivite_multi() {
        // Récupère l'identifiant de la collectivité de niveau 2
        $idx = $this->get_collectivite_par_niveau(2);
        // S'il n'y a pas de collectivité de niveau 2
        if ($idx == null || $idx == '') {
            // Compte le nombre de collectivité
            $qres = $this->get_one_result_from_db_query(
                sprintf(
                    'SELECT
                        count(om_collectivite)
                    FROM
                        %1$som_collectivite',
                    DB_PREFIXE
                ),
                array("force_return" => false, "origin" => __METHOD__)
            );
            $count = $qres["result"];
            // S'il y qu'une collectivité
            if ($count == 1) {
                // Récupère l'identifiant de la seule collectivité
                $idx = $this->get_collectivite_par_niveau(1);
            }
        }
        // Retourne l'identifiant
        return $idx;
    }

    /**
     * Surcharge - set_config__footer().
     *
     * @return void
     */
    protected function set_config__footer() {
        $footer = array();
        // Documentation du site
        $footer[] = array(
            "title" => __("Documentation"),
            "description" => __("Acceder a l'espace documentation de l'application"),
            "href" => "http://docs.openmairie.org/?project=opencimetiere&version=4.2&format=html&path=manuel_utilisateur",
            "target" => "_blank",
            "class" => "footer-documentation",
        );
        // Forum openMairie
        $footer[] = array(
            "title" => __("Forum"),
            "description" => __("Espace d'échange ouvert du projet openMairie"),
            "href" => "https://communaute.openmairie.org/c/opencimetiere",
            "target" => "_blank",
            "class" => "footer-forum",
        );
        // Portail openMairie
        $footer[] = array(
            "title" => __("openMairie.org"),
            "description" => __("Site officiel du projet openMairie"),
            "href" => "http://www.openmairie.org/catalogue/opencimetiere",
            "target" => "_blank",
            "class" => "footer-openmairie",
        );
        //
        $this->config__footer = $footer;
    }

    /**
     * Surcharge - set_config__menu().
     *
     * @return void
     */
    protected function set_config__menu() {
        parent::set_config__menu();
        $parent_menu = $this->config__menu;
        //
        $menu = array();
        // {{{ Rubrique EMPLACEMENT
        //
        $rubrik = array(
            "title" => __("emplacement"),
            "class" => "emplacement",
            "open" => array(
                "emplacement.php|",
            )
        );
        //
        $links = array();
        //
        // Entrée "Tous les emplacements"
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=emplacement",
            "class" => "emplacement",
            "title" => __("Tous les emplacements"),
            "right" => array(
                "emplacement",
                "emplacement_tab",
            ),
            "open" => array(
                "index.php|emplacement[module=tab]",
                "index.php|emplacement[module=form]",
            ),
        );
        //
        // Les natures d'emplacement seront ajoutées dynamiquement par getMenuToDisplay()
        //
        $links[] = array(
            "title" => "<hr/>",
            "right" => array(
                "contrat",
                "contrat_tab",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=contrat",
            "class" => "contrat",
            "title" => __("Contrats"),
            "right" => array(
                "contrat",
                "contrat_tab",
            ),
            "open" => array(
                "index.php|contrat[module=tab]",
                "index.php|contrat[module=form]",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=reprise_abandon",
            "class" => "reprise_abandon",
            "title" => __("Reprise sur abandon"),
            "right" => array(
                "reprise_abandon",
                "reprise_abandon_tab",
            ),
            "open" => array(
                "index.php|reprise_abandon[module=tab]",
                "index.php|reprise_abandon[module=form]",
            ),
        );
        //
        $rubrik['links'] = $links;
        //
        $menu["app-menu-rubrik-emplacement"] = $rubrik;
        // }}}

        // {{{ Rubrique RECHERCHE
        //
        $rubrik = array(
            "title" => __("recherche"),
            "class" => "recherche",
        );
        //
        $links = array();
        //
        $links[] = array(
            "href" => "../app/index.php?module=search&obj=concession",
            "class" => "recherche",
            "title" => __("recherche").' '.__("globale"),
            "right" => array(
                "recherche",
            ),
            "open" => array(
                "index.php|concession[module=search]",
            ),
        );
        //
        $links[] = array(
            "title" => "<hr/>",
            "right" => array(
                "terme",
                "terme_tab",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=terme",
            "class" => "concession_terme",
            "title" => __("concession_terme"),
            "right" => array(
                "terme",
                "terme_tab",
            ),
            "open" => array(
                "index.php|terme[module=tab]",
                "index.php|terme[module=form]",
            ),
        );
        //
        // Les emplacements libres par nature seront ajoutées dynamiquement par getMenuToDisplay()
        //
        $links[] = array(
            "title" => "<hr/>",
            "right" => array(
                "operation_en_cours_tab",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=operation_en_cours",
            "class" => "operation_en_cours",
            "title" => __("opérations en cours"),
            "right" => array(
                "operation_en_cours_tab",
            ),
            "open" => array(
                "index.php|operation_en_cours[module=tab]",
            ),
        );
        //
        $rubrik['links'] = $links;
        //
        $menu["app-menu-rubrik-recherche"] = $rubrik;
        // }}}

        // {{{ Rubrique OPERATIONS
        //
        $rubrik = array(
            "title" => __("operations"),
            "class" => "operation",
        );
        //
        $links = array();
        //
        $links[] = array(
            "class" => "category",
            "title" => __("inhumations"),
            "right" => array(
                "inhumation",
                "inhumation_tab",
            ),
        );
        //
        $links[] = array(
            "title" => "<hr/>",
            "right" => array(
                "inhumation",
                "inhumation_tab",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=inhumation",
            "class" => "operation",
            "title" => __("inhumations"),
            "right" => array(
                "inhumation",
                "inhumation_tab",
            ),
            "open" => array(
                "index.php|inhumation[module=tab]",
                "index.php|inhumation[module=form]",
            ),
        );
        //
        $links[] = array(
            "class" => "category",
            "title" => __("reductions"),
            "right" => array(
                "reduction",
                "reduction_tab",
            ),
        );
        //
        $links[] = array(
            "title" => "<hr/>",
            "right" => array(
                "reduction",
                "reduction_tab",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=reduction",
            "class" => "operation",
            "title" => __("reductions"),
            "right" => array(
                "reduction",
                "reduction_tab",
            ),
            "open" => array(
                "index.php|reduction[module=tab]",
                "index.php|reduction[module=form]",
            ),
        );
        //
        $links[] = array(
            "class" => "category",
            "title" => __("transferts"),
            "right" => array(
                "transfert",
                "transfert_tab",
            ),
        );
        //
        $links[] = array(
            "title" => "<hr/>",
            "right" => array(
                "transfert",
                "transfert_tab",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=transfert",
            "class" => "operation",
            "title" => __("transfert")." ".__("emplacement"),
            "right" => array(
                "transfert",
                "transfert_tab",
            ),
            "open" => array(
                "index.php|transfert[module=tab]",
                "index.php|transfert[module=form]",
            ),
        );
        //
        $links[] = array(
            "class" => "category",
            "title" => __("autres"),
            "right" => array(
                "operation_trt",
                "operation_trt_tab",
                "concessionplace",
                "numdossier",
            ),
        );
        //
        $links[] = array(
            "title" => "<hr/>",
            "right" => array(
                "operation_trt",
                "operation_trt_tab",
                "edition",
                "operation_en_cours_tab",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=operation_trt",
            "class" => "operation",
            "title" => __("operation(s) traitee(s)"),
            "right" => array(
                "operation_trt",
                "operation_trt_tab",
            ),
            "open" => array(
                "index.php|operation_trt[module=tab]",
                "index.php|operation_trt[module=form]",
            ),
        );
        //
        $links[] = array(
            "title" => "<hr/>",
            "right" => array(
                "emplacement_calculer_place",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_FORM."&obj=emplacement&action=91",
            "class" => "concessionplace",
            "title" => __("calcul")." ".__("place"),
            "right" => array(
                "emplacement_calculer_place",
            ),
            "open" => array(
                "index.php|emplacement[action=91]"
            ),
        );
        //
        $rubrik['links'] = $links;
        //
        $menu["app-menu-rubrik-operation"] = $rubrik;
        // }}}

        // {{{ RUBRIQUE ARCHIVE
        //
        $rubrik = array(
            "title" => __("archive"),
            "class" => "archive",
        );
        //
        $links = array();
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=emplacement_archive",
            "class" => "emplacement_archive",
            "title" => __("emplacement"),
            "right" => array(
                "emplacement_archive",
                "emplacement_archive_tab",
            ),
            "open" => array(
                "index.php|emplacement_archive[module=tab]",
                "index.php|emplacement_archive[module=form]",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=defunt_archive",
            "class" => "defunt_archive",
            "title" => __("defunt"),
            "right" => array(
                "defunt_archive",
                "defunt_archive_tab",
            ),
            "open" => array(
                "index.php|defunt_archive[module=tab]",
                "index.php|defunt_archive[module=form]",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=autorisation_archive",
            "class" => "autorisation_archive",
            "title" => __("contact"),
            "right" => array(
                "autorisation_archive",
                "autorisation_archive_tab",
            ),
            "open" => array(
                "index.php|autorisation_archive[module=tab]",
                "index.php|autorisation_archive[module=form]",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=contrat_archive",
            "class" => "contrat_archive",
            "title" => __("contrat"),
            "right" => array(
                "contrat_archive",
                "contrat_archive_tab",
            ),
            "open" => array(
                "index.php|contrat_archive[module=tab]",
                "index.php|contrat_archive[module=form]",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=operation_archive",
            "class" => "operation_archive",
            "title" => __("operation"),
            "right" => array(
                "operation_archive",
                "operation_archive_tab",
            ),
            "open" => array(
                "index.php|operation_archive[module=tab]",
                "index.php|operation_archive[module=form]",
            ),
        );
        //
        $links[] = array(
            "title" => "<hr/>",
            "right" => array(
                "emplacementfin",
                "emplacementfin_tab",
            ),
        );
        //
        $links[] = array(
            "title" => __("Emplacements archivables"),
            "href" => OM_ROUTE_TAB."&obj=emplacementfin",
            "class" => "emplacementfin",
            "right" => array(
                "emplacementfin",
                "emplacementfin_tab",
            ),
            "open" => array(
                "index.php|emplacementfin[module=tab]",
                "index.php|emplacement[module=form][action=31]",
            ),
        );
        //
        $rubrik['links'] = $links;
        //
        $menu["app-menu-rubrik-archive"] = $rubrik;
        // }}}
        //
        // PARAMETRAGE METIER
        //
        $links = array();
        //
        $links[] = array(
            "class" => "category",
            "title" => __("divers"),
            "right" => array(
                "entreprise",
                "entreprise_tab",
                "nature_emplacement",
                "nature_emplacement_tab",
                "titre_de_civilite",
                "titre_de_civilite_tab",
                "travaux_nature",
                "travaux_nature_tab",
                "sepulture_type",
                "sepulture_type_tab",
                "zone_type",
                "zone_type_tab",
                "voie_type",
                "voie_type_tab",
            ),
        );
        //
        $links[] = array(
            "title" => "<hr/>",
            "right" => array(
                "entreprise",
                "entreprise_tab",
                "nature_emplacement",
                "nature_emplacement_tab",
                "tarif",
                "tarif_tab",
                "titre_de_civilite",
                "titre_de_civilite_tab",
                "travaux_nature",
                "travaux_nature_tab",
                "sepulture_type",
                "sepulture_type_tab",
                "zone_type",
                "zone_type_tab",
                "voie_type",
                "voie_type_tab",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=entreprise",
            "class" => "entreprise",
            "title" => __("entreprise"),
            "description" => __("Une entreprise habilitée à venir effectuer des travaux sur l'emplacement."),
            "right" => array(
                "entreprise",
                "entreprise_tab",
            ),
            "open" => array(
                "index.php|entreprise[module=tab]",
                "index.php|entreprise[module=form]",
            ),
        );
        // Ajout de l'entrée de menu lien_parente
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=lien_parente",
            "class" => "lien_parente",
            "title" => __("lien_parente"),
            "description" => __("Les liens de parenté permettent de caractériser les enregistrements de généalogie."),
            "right" => array(
                "lien_parente",
                "lien_parente_tab",
            ),
            "open" => array(
                "index.php|lien_parente[module=tab]",
                "index.php|lien_parente[module=form]",
            ),
        );
        // Ajout de l'entrée de menu nature_emplacement
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=nature_emplacement",
            "class" => "nature_emplacement",
            "title" => __("nature_emplacement"),
            "description" => __("Les natures d'emplacement permettent de catégoriser les emplacements (concession, colombarium, enfeu, terrain communal, dépositoire, ossuaire)."),
            "right" => array(
                "nature_emplacement",
                "nature_emplacement_tab",
            ),
            "open" => array(
                "index.php|nature_emplacement[module=tab]",
                "index.php|nature_emplacement[module=form]",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=tarif",
            "class" => "tarif",
            "title" => __("tarif"),
            "description" => __("Les tarifs correspondent aux montants des contrats d’achat et de renouvellement d’un emplacement."),
            "right" => array(
                "tarif",
                "tarif_tab",
            ),
            "open" => array(
                "index.php|tarif[module=tab]",
                "index.php|tarif[module=form]",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=titre_de_civilite",
            "class" => "titre-de-civilite",
            "title" => __("titre_de_civilite"),
            "description" => __("Le titre de civilité est le plus fréquemment utilisé pour identifier la civilité d’une personne (Monsieur, Madame ou Mademoiselle). Il est également utilisé pour le titre ou le rang d’une personne."),
            "right" => array(
                "titre_de_civilite",
                "titre_de_civilite_tab",
            ),
            "open" => array(
                "index.php|titre_de_civilite[module=tab]",
                "index.php|titre_de_civilite[module=form]",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=sepulture_type",
            "class" => "sepulture_type",
            "title" => __("sepulture_type"),
            "description" => __("Le type de sépulture est utilisé pour décrire une concession. Exemples : “Fosse maçonnée haute”, “Cavurne”, “Pierre tombale”, “Caveau T2 haut”, “Caveau T2 bas”, …"),
            "right" => array(
                "sepulture_type",
                "sepulture_type_tab",
            ),
            "open" => array(
                "index.php|sepulture_type[module=tab]",
                "index.php|sepulture_type[module=form]",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=travaux_nature",
            "class" => "travaux_nature",
            "title" => __("travaux_nature"),
            "description" => __("La nature des travaux est utilisée pour décrire les travaux sur un emplacement. Exemples : “Enlèvement porte”, “Démolition-Reconstruction à l’identique”, “Creusement”, “Surélévation”, …"),
            "right" => array(
                "travaux_nature",
                "travaux_nature_tab",
            ),
            "open" => array(
                "index.php|travaux_nature[module=tab]",
                "index.php|travaux_nature[module=form]",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=zone_type",
            "class" => "zone_type",
            "title" => __("zone_type"),
            "description" => __("Le type de zone est utilisé pour catégoriser une zone dans le système de localisation. Exemples : “Carré”, “Extension”, “Section”, …"),
            "right" => array(
                "zone_type",
                "zone_type_tab",
            ),
            "open" => array(
                "index.php|zone_type[module=tab]",
                "index.php|zone_type[module=form]",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=voie_type",
            "class" => "voie_type",
            "title" => __("voie_type"),
            "description" => __("Le type de voie est utilisé pour catégoriser une voie dans le système de localisation. Exemples : “Allée”, “Place”, “Rangée”, …"),
            "right" => array(
                "voie_type",
                "voie_type_tab",
            ),
            "open" => array(
                "index.php|voie_type[module=tab]",
                "index.php|voie_type[module=form]",
            ),
        );
        //
        $links[] = array(
            "class" => "category",
            "title" => __("localisation"),
            "right" => array(
                "plans",
                "plans_tab",
                "cimetiere",
                "cimetiere_tab",
                "zone",
                "zone_tab",
                "voie",
                "voie_tab",
            ),
        );
        //
        $links[] = array(
            "title" => "<hr/>",
            "right" => array(
                "cimetiere",
                "cimetiere_tab",
                "zone",
                "zone_tab",
                "voie",
                "voie_tab",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=cimetiere",
            "class" => "cimetiere",
            "title" => __("cimetiere"),
            "description" => __("Paramétrage des cimetières."),
            "right" => array(
                "cimetiere",
                "cimetiere_tab",
            ),
            "open" => array(
                "index.php|cimetiere[module=tab]",
                "index.php|cimetiere[module=form]",
                "index.php|cimetiere[module=map][mode=tab_sig]",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=zone",
            "class" => "zone",
            "title" => __("zone"),
            "description" => __("Paramétrage des zones. Un cimetière se compose de plusieurs zones (comme des carrés ou des sections)."),
            "right" => array(
                "zone",
                "zone_tab",
            ),
            "open" => array(
                "index.php|zone[module=tab]",
                "index.php|zone[module=form]",
                "index.php|zone[module=map][mode=tab_sig]",
            ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=voie",
            "class" => "voie",
            "title" => __("voie"),
            "description" => __("Paramétrage des voies. Un emplacement est adressé par un numéro, éventullement un complément de numéro et une voie. Une zone se compose de plusieurs voies (comme des allées ou des rangées)."),
            "right" => array(
                "voie",
                "voie_tab",
            ),
            "open" => array(
                "index.php|voie[module=tab]",
                "index.php|voie[module=form]",
                "index.php|voie[module=map][mode=tab_sig]",
            ),
        );
        //
        $links[] = array(
            "title" => "<hr/>",
            "right" => array(
                "plans",
                "plans_tab",
            ),
            "parameters" => array("option_localisation" => "plan", ),
        );
        //
        $links[] = array(
            "href" => OM_ROUTE_TAB."&obj=plans",
            "class" => "plans",
            "title" => __("plans"),
            "description" => __("Paramétrage des plans. Un plan correspond à un croquis d’un cimetière ou d’une partie d’un cimetière. Un emplacement se localise sur un plan grâce à un point."),
            "right" => array(
                "plans",
                "plans_tab",
            ),
            "open" => array(
                "index.php|plans[module=tab]",
                "index.php|plans[module=form]",
            ),
            "parameters" => array("option_localisation" => "plan", ),
        );
        $link_habillage[] = array(
            "href" => OM_ROUTE_TAB."&obj=habillage",
            "class" => "habillage",
            "title" => __("habillage"),
            "description" => __("Paramétrage des habillages."),
            "right" => array(
                "habillage",
                "habillage_tab",
            ),
            "open" => array(
                "index.php|habillage[module=tab]",
                "index.php|habillage[module=form]",
            ),
            "parameters" => array("option_localisation" => "sig_interne", ),
        );
        //
        $parent_menu["om-menu-rubrik-parametrage"]["links"] = array_merge(
            $links,
            $parent_menu["om-menu-rubrik-parametrage"]["links"]
        );

        // On veut insérer le lien de habillage juste après om_sig_flux
        // Parcours du tableau pour trouver la position exacte de om_sig_flux
        $position_om_sig_flux = false;
        foreach ($parent_menu["om-menu-rubrik-administration"]["links"] as $key => $link) {
            if (isset($link['class']) && $link['class'] === 'om_sig_flux') {
                $position_om_sig_flux = $key;
                break;
            }
        }
        // Si trouvé, on insère juste après (position + 1)
        if ($position_om_sig_flux !== false) {
            $position_habillage = $position_om_sig_flux + 1;
            array_splice($parent_menu["om-menu-rubrik-administration"]["links"], $position_habillage, 0, $link_habillage);
        }
        //
        $this->config__menu = array_merge(
            $menu,
            $parent_menu
        );
    }

    /**
     * Instanciation de la classe *om_import*.
     *
     * @param array $args Arguments à passer au constructeur.
     *
     * @return om_import
     */
    function get_inst__om_import($args = array()) {
        if (file_exists("../obj/app_om_import.class.php")) {
            require_once "../obj/app_om_import.class.php";
            $class_name = "app_om_import";
        } else {
            require_once PATH_OPENMAIRIE."om_import.class.php";
            $class_name = "import";
        }
        return new $class_name();
    }

    /**
     * Permet de générer la liste des généalogie pour un défunt ou pour un contact.
     *
     * @param $defunt_or_autorisation Il faut spécifier si c'est le texte d'un défunt ou d'un contact
     * @param $id Identifiant du défunt ou du contact
     *
     * @return string $text_genealogie | null
     */
    function generate_text_genealogie($defunt_or_autorisation, $id) {

        // Si le paramètre n'est pas spécifié
        if (($defunt_or_autorisation != 'defunt' && $defunt_or_autorisation != 'autorisation') || is_int(intval($id)) == false) {
            return null;
        }
        // Si le paramètre est à défunt on change la clause where de la requête sql
        if ($defunt_or_autorisation == 'defunt') {
            $whereclause = sprintf('(defunt_p1 = %1$d OR defunt_p2 = %1$d)', $id);
        }

        // Si le paramètre est à autorisation on change la clause where de la requête sql
        if ($defunt_or_autorisation == 'autorisation') {
            $whereclause = sprintf('(autorisation_p1 = %1$d OR autorisation_p2 = %1$d)', $id);
        }

        // Il est possible que la requête soit lancé deux si jamais un lien de parenté
        // de type même personne est identifié
        $template_sql_lien_parente = '
                SELECT
                    defunt_p1,
                    defunt_p2,
                    autorisation_p1,
                    autorisation_p2,
                    lien_parente.libelle as lien_parente_libelle,
                    lien_parente.lien_inverse as lien_inverse,
                    (SELECT
                        CONCAT_WS(\' \', defunt.nom, defunt.marital, defunt.prenom) as defunt_p1_nom
                    FROM
                        %1$sdefunt
                    WHERE
                        defunt = genealogie.defunt_p1),

                    (SELECT
                        CONCAT_WS(\' \', defunt.nom, defunt.marital, defunt.prenom) as defunt_p2_nom
                    FROM
                        %1$sdefunt
                    WHERE
                        defunt = genealogie.defunt_p2),

                    (SELECT
                        CONCAT_WS(\' \', autorisation.nom, autorisation.marital, autorisation.prenom) as autorisation_p1_nom
                    FROM
                        %1$sautorisation
                    WHERE
                        autorisation = genealogie.autorisation_p1
                    ),

                    (SELECT
                        CONCAT_WS(\' \', autorisation.nom, autorisation.marital, autorisation.prenom) as autorisation_p2_nom
                    FROM
                        %1$sautorisation
                    WHERE
                        autorisation = genealogie.autorisation_p2
                    ),

                    lien_parente.meme_personne
                FROM
                    %1$sgenealogie
                    INNER JOIN %1$slien_parente ON genealogie.lien_parente=lien_parente.lien_parente
                WHERE
                    %2$s
                ';

        $liens_genealogie = $this->get_all_results_from_db_query(
            sprintf(
                $template_sql_lien_parente,
                DB_PREFIXE,
                $whereclause
            ),
            array('force_return' => false, 'origin' => __METHOD__)
        );

        $lien_meme_personne = array();
        $text_genealogie = '<ul class="liste_genealogie">';
        $texte_template = "<li> %s de %s%s </li>";
        // Génération du texte de la personne dont l'id est passé en paramètre
        foreach ($liens_genealogie['result'] as $lien_genealogie) {
            // Soit notre personne est en première position
            // on prend donc la deuxième
            if ($lien_genealogie[$defunt_or_autorisation.'_p1'] == $id) {
                $lien_parente = $lien_genealogie['lien_parente_libelle'];
                $defunt = $lien_genealogie['defunt_p2_nom'];
                $autorisation = $lien_genealogie['autorisation_p2_nom'];
            }

            // Soit notre personne est en deuxième position
            // on prend donc la première
            if ($lien_genealogie[$defunt_or_autorisation.'_p2'] == $id) {
                $lien_parente = $lien_genealogie['lien_inverse'];
                $defunt = $lien_genealogie['defunt_p1_nom'];
                $autorisation = $lien_genealogie['autorisation_p1_nom'];
            }

            // Si le lien indique la même personne
            if ($lien_genealogie['meme_personne'] == 't') {
                // Récupération du lien même personne afin de récupérer les liens de l'autre personne
                if ($lien_genealogie[$defunt_or_autorisation.'_p1'] == $id) {
                    $lien_parente = $lien_genealogie['lien_inverse'];
                }
                if ($lien_genealogie[$defunt_or_autorisation.'_p2'] == $id) {
                    $lien_parente = $lien_genealogie['lien_parente_libelle'];
                }
                $texte_template = "<li> Même personne que le %s %s%s </li>";
                $lien_meme_personne[] = $lien_genealogie;
            }

            // Ajout du texte de généalogie
            $text_genealogie .= sprintf(
                $texte_template,
                $lien_parente,
                $defunt,
                $autorisation
            );
        }

        // Gestion des liens même personne
        $id_meme_personne = 0;
        $d_or_c_meme_personne = 'defunt';
        // Si il y a un lien même personne
        if (! empty($lien_meme_personne)) {

            // Si c'est un défunt qui est passé en paramètre alors on vérifie sont identifiant
            // et on récupère la deuxième personne lié indiqué comme "même personne"
            if ($defunt_or_autorisation == 'defunt') {
                if ($lien_meme_personne[0]['defunt_p1'] == $id) {
                    if (!empty($lien_meme_personne[0]['defunt_p2'])) {
                        $id_meme_personne = $lien_meme_personne[0]['defunt_p2'];
                    }
                    if (!empty($lien_meme_personne[0]['autorisation_p2'])) {
                        $id_meme_personne = $lien_meme_personne[0]['autorisation_p2'];
                        $d_or_c_meme_personne = 'autorisation';
                    }
                }
                if ($lien_meme_personne[0]['defunt_p2'] == $id) {
                    if (!empty($lien_meme_personne[0]['defunt_p1'])) {
                        $id_meme_personne = $lien_meme_personne[0]['defunt_p1'];
                    }
                    if (!empty($lien_meme_personne[0]['autorisation_p1'])) {
                        $id_meme_personne = $lien_meme_personne[0]['autorisation_p1'];
                        $d_or_c_meme_personne = 'autorisation';
                    }
                }
            }

            // Si c'est une autorisation qui est passé en paramètre alors on vérifie sont identifiant
            // et on récupère la deuxième personne lié indiqué comme "même personne"
            if ($defunt_or_autorisation == 'autorisation') {
                if ($lien_meme_personne[0]['autorisation_p1'] == $id) {
                    if (!empty($lien_meme_personne[0]['defunt_p2'])) {
                        $id_meme_personne = $lien_meme_personne[0]['defunt_p2'];
                    }
                    if (!empty($lien_meme_personne[0]['autorisation_p2'])) {
                        $id_meme_personne = $lien_meme_personne[0]['autorisation_p2'];
                        $d_or_c_meme_personne = 'autorisation';
                    }
                }
                if ($lien_meme_personne[0]['autorisation_p2'] == $id) {
                    if (!empty($lien_meme_personne[0]['defunt_p1'])) {
                        $id_meme_personne = $lien_meme_personne[0]['defunt_p1'];
                    }
                    if (!empty($lien_meme_personne[0]['autorisation_p1'])) {
                        $id_meme_personne = $lien_meme_personne[0]['autorisation_p1'];
                        $d_or_c_meme_personne = 'autorisation';
                    }
                }
            }

            // Construction de la clause where en fonction du type de la 2ème personne indiqué comme "même personne"
            if ($d_or_c_meme_personne == 'defunt') {
                $whereclause = sprintf('(defunt_p1 = %1$d OR defunt_p2 = %1$d)', $this->db->escapeSimple(intval($id_meme_personne)));
            }
            if ($d_or_c_meme_personne == 'autorisation') {
                $whereclause = sprintf('(autorisation_p1 = %1$d OR autorisation_p2 = %1$d)', $this->db->escapeSimple(intval($id_meme_personne)));
            }

            $qliens_meme_personne = $this->get_all_results_from_db_query(
                sprintf(
                    $template_sql_lien_parente,
                    DB_PREFIXE,
                    $whereclause
                ),
                array('force_return' => false, 'origin' => __METHOD__)
            );

            $texte_template = "<li> %s de %s%s </li>";
            foreach ($qliens_meme_personne['result'] as $lien_genealogie) {
                // Si le lien est même personne alors on ne le récupère pas
                if ($lien_genealogie['meme_personne'] == 't') {
                    continue;
                }

                // Soit la personne indiqué comme "même personne" est en première position
                // on prend donc la deuxième
                if ($lien_genealogie[$d_or_c_meme_personne.'_p1'] == $id_meme_personne) {
                    $lien_parente = $lien_genealogie['lien_parente_libelle'];
                    $defunt = $lien_genealogie['defunt_p2_nom'];
                    $autorisation = $lien_genealogie['autorisation_p2_nom'];
                }

                // Soit la personne indiqué comme "même personne" est en deuxième position
                // on prend donc la première
                if ($lien_genealogie[$d_or_c_meme_personne.'_p2'] == $id_meme_personne) {
                    $lien_parente = $lien_genealogie['lien_inverse'];
                    $defunt = $lien_genealogie['defunt_p1_nom'];
                    $autorisation = $lien_genealogie['autorisation_p1_nom'];
                }

                // Ajout du texte de généalogie
                $text_genealogie .= sprintf(
                    $texte_template,
                    $lien_parente,
                    $defunt,
                    $autorisation
                );
            }
        }
        // Fermeture de la liste des liens généalogiques
        $text_genealogie .= "</ul>";

        return $text_genealogie;
    }

    /**
     * Traitement des erreurs retournées par l'abstracteur electronicsignature.
     *
     * @param electronicsignature_exception $exception Exception retournée par l'abstracteur.
     *
     * @return void
     */
    public function handle_geocimetiere_exception(geocimetiere_exception $exception) {
        $this->correct = false;
        $this->addToLog($exception->getMessage(), DEBUG_MODE);
        $this->message = array();
        if (! in_array($exception->getMessage(),$this->message)){
            $this->addToMessage('error', $exception->getMessage());
        }
    }


    /**
     * Retourne une instance du connecteur geocimetiere, et la créer si elle n'existe pas.
     *
     * @param  boolean $with_handle_error Flag pour afficher ou non le message d'erreur à l'utilisat
eur.
     * @return geocimetiere        Instance de l'abstracteur.
     */
    public function get_geocimetiere_instance($with_handle_error = true) {
        if(isset($this->geocimetiere_instance)) {
            return $this->geocimetiere_instance;
        }
        // Instanciation du connecteur geocimetiere
        try {
            require_once "geocimetiere.class.php";
            $collectiviteParams = $this->getCollectivite($_SESSION['collectivite']);
            $extra_params = array(
                "inst_framework" => $this,
            );
            $this->geocimetiere_instance = new geocimetiere($collectiviteParams, $extra_params);
        } catch (geocimetiere_exception $e) {
           if ($with_handle_error === true) {
               $this->handle_geocimetiere_exception($e);
               return false;
            }
        }
        return $this->geocimetiere_instance;
    }

    /**
     * Surcharge - getMenuToDisplay().
     *
     * Permet de générer dynamiquement les entrées de menu pour les natures d'emplacement
     * à partir de la table nature_emplacement.
     *
     * @return array
     */
    function getMenuToDisplay() {
        // Appel de la méthode parente pour obtenir le menu de base
        $menu = parent::getMenuToDisplay();
        
        // Si l'utilisateur n'est pas authentifié, on retourne le menu tel quel
        if ($this->authenticated == false) {
            return $menu;
        }
        
        // Recherche de l'index de la rubrique "emplacement" dans le menu
        // Le menu est indexé numériquement (0, 1, 2, ...), pas par clés nommées
        $rubrique_index = null;
        foreach ($menu as $index => $rubrique) {
            if (isset($rubrique['class']) && $rubrique['class'] === 'emplacement') {
                $rubrique_index = $index;
                break;
            }
        }
        
        // Si la rubrique n'existe pas dans le menu filtré, on la récupère depuis config__menu
        if ($rubrique_index === null) {
            $full_menu = $this->get_config__menu();
            if (!isset($full_menu["app-menu-rubrik-emplacement"])) {
                return $menu;
            }
            // On ajoute la rubrique au menu
            $menu[] = $full_menu["app-menu-rubrik-emplacement"];
            $rubrique_index = count($menu) - 1;
        }
        
        // Récupération des natures d'emplacement depuis la base de données
        $qres = $this->get_all_results_from_db_query(
            sprintf(
                'SELECT
                    nature_emplacement,
                    code,
                    libelle
                FROM
                    %snature_emplacement
                WHERE
                    (om_validite_debut IS NULL OR om_validite_debut <= CURRENT_DATE)
                    AND (om_validite_fin IS NULL OR om_validite_fin >= CURRENT_DATE)
                ORDER BY
                    nature_emplacement',
                DB_PREFIXE
            )
        );
        
        // Si on a bien récupéré des natures d'emplacement
        if ($qres['code'] === 'OK' && !empty($qres['result'])) {
            // Préparation des nouveaux liens à insérer
            $new_nature_links = array();
            
            // Construction du tableau des droits pour le séparateur
            $separator_rights = array();
            foreach ($qres['result'] as $nature) {
                $separator_rights[] = $nature['code'];
                $separator_rights[] = $nature['code'].'_tab';
            }
            
            // Ajout du séparateur avant les natures
            $new_nature_links[] = array(
                "title" => "<hr/>",
                "right" => $separator_rights,
            );
            
            // Variable pour stocker si un lien de nature est sélectionné
            $nature_selected = false;
            
            // Ajout d'une entrée de menu pour chaque nature d'emplacement
            foreach ($qres['result'] as $nature) {
                $code = $nature['code'];
                $libelle = $nature['libelle'];
                $nature_id = $nature['nature_emplacement'];
                
                // Création d'un advs_id unique pour cette nature
                $advs_id = 'nature_' . $nature_id . '_' . str_replace('.', '', microtime(true));
                
                // Stockage des critères de recherche avancée en session
                $_SESSION["advs_ids"][$advs_id] = serialize(array(
                    "advanced-search-submit" => "",
                    "nature" => $nature_id,
                ));
                
                // Vérification si ce lien correspond à la page actuelle
                // On vérifie que l'advs_id correspond à cette nature SANS filtre libre
                // (les listings "libres" sont gérés séparément dans la rubrique Recherche)
                $is_selected = false;
                if (isset($_GET['advs_id']) && isset($_SESSION["advs_ids"][$_GET['advs_id']])) {
                    $current_advs_criteria = unserialize($_SESSION["advs_ids"][$_GET['advs_id']]);
                    if (
                        isset($current_advs_criteria['nature'])
                        && $current_advs_criteria['nature'] == $nature_id
                        && empty($current_advs_criteria['libre'])
                    ) {
                        $is_selected = true;
                        $nature_selected = true;
                    }
                }
                
                $new_nature_links[] = array(
                    "href" => OM_ROUTE_TAB."&obj=emplacement&advs_id=".$advs_id,
                    "class" => $code,
                    "title" => $libelle,
                    "selected" => $is_selected ? "selected" : null,
                    "right" => array(
                        $code,
                        $code."_tab",
                    ),
                    "open" => array(
                        "index.php|emplacement[module=tab][advs_id=".$advs_id."]" ,
                        "index.php|emplacement[module=form][advs_id=".$advs_id."]",
                        "localisation_plan.php|emplacement",
                        "localisation_plan_edit.php|emplacement",
                        "localisation_plan_view.php|emplacement",
                    ),
                );
            }
            
            // Recherche de la position d'insertion (après "Tous les emplacements")
            $insert_position = 1;
            $tous_emplacements_index = null;
            foreach ($menu[$rubrique_index]["links"] as $link_index => $link) {
                if (isset($link['class']) && $link['class'] === 'emplacement') {
                    $insert_position = $link_index + 1;
                    $tous_emplacements_index = $link_index;
                    break;
                }
            }
            
            // Si une nature est sélectionnée, on retire la sélection de "Tous les emplacements"
            if ($nature_selected && $tous_emplacements_index !== null) {
                unset($menu[$rubrique_index]["links"][$tous_emplacements_index]["selected"]);
            }
            
            // Insertion des nouveaux liens avec array_splice
            array_splice($menu[$rubrique_index]["links"], $insert_position, 0, $new_nature_links);
        }
        
        // -----------------------------------------------------------------------
        // Génération dynamique des entrées "libres" dans la rubrique RECHERCHE
        // Pour chaque nature d'emplacement ayant listing_libre = true, on ajoute
        // une entrée dans le menu qui filtre emplacement par nature + libre='Oui'.
        // -----------------------------------------------------------------------
        
        // Recherche de l'index de la rubrique "recherche" dans le menu filtré
        $rubrique_recherche_index = null;
        foreach ($menu as $index => $rubrique) {
            if (isset($rubrique['class']) && $rubrique['class'] === 'recherche') {
                $rubrique_recherche_index = $index;
                break;
            }
        }
        
        // Si la rubrique n'existe pas dans le menu filtré, on la récupère depuis config__menu
        if ($rubrique_recherche_index === null) {
            $full_menu = $this->get_config__menu();
            if (!isset($full_menu["app-menu-rubrik-recherche"])) {
                return $menu;
            }
            $menu[] = $full_menu["app-menu-rubrik-recherche"];
            $rubrique_recherche_index = count($menu) - 1;
        }
        
        // Récupération des natures d'emplacement avec listing_libre = true
        $qres_libre = $this->get_all_results_from_db_query(
            sprintf(
                'SELECT
                    nature_emplacement,
                    code,
                    libelle
                FROM
                    %snature_emplacement
                WHERE
                    listing_libre = true
                    AND (om_validite_debut IS NULL OR om_validite_debut <= CURRENT_DATE)
                    AND (om_validite_fin IS NULL OR om_validite_fin >= CURRENT_DATE)
                ORDER BY
                    nature_emplacement',
                DB_PREFIXE
            )
        );
        
        if ($qres_libre['code'] === 'OK' && !empty($qres_libre['result'])) {
            $new_libre_links = array();
            
            // Séparateur conditionné par l'accès à emplacement
            $new_libre_links[] = array(
                "title" => "<hr/>",
                "right" => array(
                    "emplacement",
                    "emplacement_tab",
                ),
            );
            
            // Déserialisation des critères de la page courante (pour la détection "selected")
            $current_advs_criteria_libre = array();
            if (isset($_GET['advs_id']) && isset($_SESSION["advs_ids"][$_GET['advs_id']])) {
                $current_advs_criteria_libre = unserialize($_SESSION["advs_ids"][$_GET['advs_id']]);
            }
            
            $libre_selected = false;
            
            foreach ($qres_libre['result'] as $nature) {
                $code = $nature['code'];
                $libelle = $nature['libelle'];
                $nature_id = $nature['nature_emplacement'];
                
                // Création d'un advs_id unique pour ce filtre nature + libre
                $advs_id = 'libre_' . $nature_id . '_' . str_replace('.', '', microtime(true));
                
                // Stockage des critères : nature + libre = 'Oui'
                $_SESSION["advs_ids"][$advs_id] = serialize(array(
                    "advanced-search-submit" => "",
                    "nature" => $nature_id,
                    "libre" => "Oui",
                ));
                
                // Détection si ce lien est actif (même nature ET libre='Oui')
                $is_selected = (
                    isset($current_advs_criteria_libre['nature'])
                    && $current_advs_criteria_libre['nature'] == $nature_id
                    && isset($current_advs_criteria_libre['libre'])
                    && $current_advs_criteria_libre['libre'] === 'Oui'
                );
                
                if ($is_selected) {
                    $libre_selected = true;
                }
                
                $new_libre_links[] = array(
                    "href" => OM_ROUTE_TAB."&obj=emplacement&advs_id=".$advs_id,
                    "class" => $code."_libre",
                    "title" => $libelle.' - '.__("libres"),
                    "selected" => $is_selected ? "selected" : null,
                    "right" => array(
                        "emplacement",
                        "emplacement_tab",
                    ),
                    "open" => array(
                        "index.php|emplacement[module=tab][advs_id=".$advs_id."]",
                        "index.php|emplacement[module=form][advs_id=".$advs_id."]",
                    ),
                );
            }
            
            // Si une entrée libre est active :
            // 1. Désélectionner tous les liens de la rubrique emplacement que le parent
            //    aurait pu marquer via is_elem_selected (notamment "Tous les emplacements"
            //    qui match tout URL obj=emplacement)
            // 2. Sélectionner la rubrique recherche pour qu'elle reste ouverte
            if ($libre_selected) {
                if ($rubrique_index !== null) {
                    foreach ($menu[$rubrique_index]["links"] as $li => $l) {
                        unset($menu[$rubrique_index]["links"][$li]["selected"]);
                    }
                    unset($menu[$rubrique_index]["selected"]);
                }
                // Ouvrir et sélectionner la rubrique recherche
                $menu[$rubrique_recherche_index]["selected"] = "selected";
            }
            
            // Insertion avant le séparateur "opérations en cours"
            // On cherche le lien "operation_en_cours" pour insérer juste avant son <hr/>
            $insert_position = count($menu[$rubrique_recherche_index]["links"]);
            foreach ($menu[$rubrique_recherche_index]["links"] as $link_index => $link) {
                if (
                    isset($link['title'])
                    && $link['title'] === "<hr/>"
                    && isset($link['right'])
                    && in_array("operation_en_cours_tab", $link['right'])
                ) {
                    $insert_position = $link_index;
                    break;
                }
            }
            
            array_splice(
                $menu[$rubrique_recherche_index]["links"],
                $insert_position,
                0,
                $new_libre_links
            );
        }
        
        return $menu;
    }
}
