<?php
//$Id$
//gen openMairie le 10/08/2020 10:08

require_once "../gen/obj/unite.class.php";

class unite extends unite_gen {


    /**
     * Définition des actions disponibles sur la classe.
     *
     * @return void
     */
    function init_class_actions() {
        // On récupère les actions génériques définies dans la méthode
        // d'initialisation de la classe parente
        parent::init_class_actions();
        // ACTION - 007 - unite_perimetre
        //
        $this->class_actions[7] = array (
            "identifier" => "unite_perimetre",
            "view" => "view_unite_perimetre",
            "permission_suffix" => "consulter",
        );

        // ACTION - 008 - is_bureau
        //
        $this->class_actions[8] = array (
            "identifier" => "is_bureau",
            "view" => "view_is_bureau",
            "permission_suffix" => "consulter",
        );
        // ACTION - 009 - import-unites
        //
        $this->class_actions[9] = array (
            "identifier" => "import-unites",
            "view" => "view_import_unites",
            "permission_suffix" => "importer",
        );
        // ACTION - 010 - change_libelle
        //
        $this->class_actions[10] = array (
            "identifier" => "change_libelle",
            "view" => "view_code_obligatoire",
            "permission_suffix" => "consulter",
        );
    }


    /**
     * Clause select pour la requête de sélection des données de l'enregistrement.
     *
     * @return array liste des champs dans leur ordre d'apparition
     */
    function get_var_sql_forminc__champs() {
        // ré-ordonne les champs pour pouvoir les afficher correctement dans setLayout
        return array(
            "unite",
            "id_reu",
            "libelle",
            "type_unite",
            "ordre",
            "adresse1",
            "adresse2",
            "cp",
            "ville",
            "geom",
            "coordinates",
            "'' as lon",
            "'' as lat",
            "perimetre",
            "type_unite_contenu",
            "om_validite_debut",
            "om_validite_fin",
            "code_unite",
            "canton",
            "circonscription",
            "commune",
            "departement"
        );
    }

    /**
     * SETTER FORM - setType.
     *
     * @param formulaire $form Instance formulaire.
     * @param integer $maj Identifant numérique de l'action.
     *
     * @return void
     */
    function setType(&$form, $maj) {
        parent::setType($form, $maj);
        $form->setType('id_reu', 'hiddenstatic');
        //Les coordonnées, la latitude et la longitude sont récupérées automatiquement via l'adresse
        //elles n'ont pas besoin d'être affichées et saisies lors de l'ajout et de la modification
        if ($maj<2) {
            $form->setType('coordinates', 'hiddenstatic');
            $form->setType('lon', 'hiddenstatic');
            $form->setType('lat', 'hiddenstatic');
        }
    }

    /**
     * Permet de définir l’attribut “onchange” sur chaque champ.
     *
     * @param object  &$form Formumaire
     * @param integer $maj   Mode d'insertion
     */
    function setOnchange(&$form, $maj) {
        parent::setOnchange($form, $maj);

        $form->setOnchange(
            'type_unite_contenu',
            'recuperer_perimetre(this.value);'
        );

        $form->setOnchange(
            'type_unite',
            "filterSelect(this.value,'type_unite_contenu','type_unite','unite');
            obligatoireSelonType(this.value)"
        );
    }

    /**
     * SETTER FORM - setLib
     *
     * @param formulaire $form Instance formulaire.
     * @param integer $maj Identifant numérique de l'action.
     *
     * @return void
     */
    function setLib(&$form, $maj) {
        //libelle des champs
        parent::setLib($form, $maj);

        $form->setLib('type_unite', 'type');
        $form->setLib('id_reu', 'id REU');
        $form->setLib('adresse1', 'adresse : ');
        $form->setLib('adresse2', 'complément d\'adresse : ');
        $form->setLib('cp', __('cp'));
        $form->setLib('ville', __('ville'));
        $form->setLib('geom', '');
        $form->setLib('coordinates', '');
        $form->setLib('type_unite_contenu', 'type voulu');
        $form->setLib('code_unite', 'code unite');
        $form->setLib('om_validite_debut', 'début de validité');
        $form->setLib('om_validite_fin', 'fin de validité');

        // Le champ est marqué comme obligatoire si l'unité à un type ayant
        // un comportement de bureau de vote
        if (! empty($this->getVal('type_unite'))) {
            if ($this->is_bureau($this->getVal('type_unite'))) {
                $form->setLib('code_unite', 'code unite *');
            }
        }
    }

    /**
     * SETTER FORM - setLayout
     *
     * @param formulaire $form Instance formulaire.
     * @param integer $maj Identifant numérique de l'action.
     *
     * @return void
     */
    function setLayout(&$form, $maj) {
        // Fieldset unité contiens dans l'ordre : libellé, type et ordre
        $form->setFieldset('libelle', 'D', ' '._('unite').' ', 'collapsible');
            $form->setBloc('libelle', 'D', "", "group");
            $form->setBloc('ordre', 'F');
        $form->setFieldset('ordre', 'F', '');

        // Fieldset adresse contiens dans l'ordre : adresse1, 2, code postal, ville
        // le geom, les coordonnées, la longitude et la latitude
        $form->setFieldset('adresse1', 'D', ' '._('adresse').' ', 'collapsible');
            $form->setBloc('adresse1', 'D', "", "group");
            $form->setBloc('ville', 'F');
            $form->setBloc('geom', 'D', "", "group");
            $form->setBloc('lat', 'F');
        $form->setFieldset('lat', 'F', '');

        // Fieldset perimetre contiens dans l'ordre : perimetre et type d'unité contenu voulu
        $form->setFieldset('perimetre', 'D', ' '._('perimetre').' ', 'collapsible');
            $form->setBloc('perimetre', 'D', "", "group");
            $form->setBloc('type_unite_contenu', 'F');
        $form->setFieldset('type_unite_contenu', 'F', '');

        // Fieldset code contiens dans l'ordre : code bureau, canton,
        // circonscription, commune, departement
        $form->setFieldset('code_unite', 'D', ' '._('code').' ', 'collapsible');
            $form->setBloc('code_unite', 'D', "", "group");
            $form->setBloc('departement', 'F');
        $form->setFieldset('departement', 'F', '');

        // Fieldset prefecture contiens dans l'ordre : date de validité de debut et de fin
        $form->setFieldset('om_validite_debut', 'D', ' '._('validite').' ', 'collapsible');
            $form->setBloc('om_validite_debut', 'D', "", "group");
            $form->setBloc('om_validite_fin', 'F');
        $form->setFieldset('om_validite_fin', 'F', '');
    }

    /**
     * SETTER FORM - set_form_default_values
     *
     * @param formulaire $form Instance formulaire.
     * @param integer $maj Identifant numérique de l'action.
     * @param integer $validation Marqueur de validation du formulaire.
     *
     * @return void
     */
    function set_form_default_values(&$form, $maj, $validation) {
        if ($validation==0) {
            //Ajout de valeur par défaut pour la latitude et la longitude si aucune valeur n'existe
            $lon = "4.631";
            if ($this->f->getParameter("lon")!='') {
                $lon = $this->f->getParameter("lon");
            }

            $lat = "43.677";
            if ($this->f->getParameter("lat")!= '') {
                $lat = $this->f->getParameter("lat");
            }

            $form->setVal('lon', $lon);
            $form->setVal('lat', $lat);
        }
    }

    /**
     * Compte à l'aide d'une requête le nombre d'unité
     * valide, ayant pour code unité le code passé en paramètre.
     *
     * Si des résultats sont récupérés renvoie false sinon
     * renvoie true.
     *
     * Si la requête échoue renvoie false
     *
     * @param integer code à chercher
     * @return boolean
     */
    public function is_code_unite_unique($codeUnite) {
        $sqlNotThisUnit = '';
        if ($this->getVal('unite') != null && $this->getVal('unite') != '') {
            $sqlNotThisUnit = sprintf("AND unite != '%s'", $this->getVal('unite'));
        }
        $sql = sprintf(
            'SELECT
                count(unite)
            FROM
                %1$sunite
            WHERE
                code_unite = \'%2$s\'
                AND (unite.om_validite_fin IS NULL
                    OR unite.om_validite_fin > CURRENT_DATE)
                %3$s',
            DB_PREFIXE,
            $codeUnite,
            $sqlNotThisUnit
        );
        $res = $this->f->get_one_result_from_db_query($sql);
        if ($res['code'] != 'KO') {
            return $res['result'] == 0;
        }
        return false;
    }

    /**
     * Vérifie la validité des valeurs en mode CREATE & UPDATE.
     *
     * @param array $val Tableau des valeurs brutes.
     * @param null &$dnu1 @deprecated  Ne pas utiliser.
     * @param null $dnu2 @deprecated  Ne pas utiliser.
     *
     * @return void
     */
    function verifier($val = array(), &$dnu1 = null, $dnu2 = null) {
        $result = parent::verifier($val);
        // Vérifie en ajout et en modification que le code de l'unité est unique
        if (isset($val['code_unite']) && $val['code_unite'] != ''
            && (! $this->is_code_unite_unique($val['code_unite']))) {
                $this->addToMessage('Le code de l\'unité doit être unique');
                $this->correct = false;
                return false;
        }
        if (! $this->validate_type_unite($val['type_unite'])) {
            $this->correct = false;
            $result = false;
        }
        if (! empty($val['type_unite_contenu']) && ! $this->validate_type_unite_contenu($val['type_unite_contenu'])) {
            $this->correct = false;
            $result = false;
        }
        // Vérifie si une unité possédant le même nom n'existe pas déjà
        if (! $this->isUnique('libelle', $val['libelle'])) {
            $this->addToMessage('ATTENTION : une unité portant ce nom existe déjà !');
        }
        // Le code unité doit obligatoirement être saisi pour les bureau de vote
        $typeUnite = $this->f->get_element_by_id('type_unite', $val['type_unite']);
        if ($this->f->boolean_string_to_boolean($typeUnite->getVal('bureau_vote'))) {
            if (empty($val['code_unite'])) {
                $this->addToMessage('Le code unité est obligatoire pour les bureaux de vote !');
                $this->correct = false;
                $result = false;
            }
        }
        // Si une unité contiens d'autres unité alors son type d'unité contenu
        // ne peut pas être modifié et ça doit être un périmètre
        // Son type d'unité peut être modifié que si il respecte la hierarchie
        // (il doit donc être plus grand que le type d'unité contenu)
        if ($this->est_parent()) {
            if ($val['perimetre'] == false || $val['perimetre'] == 'Non') {
                $this->addToMessage("L'unité est un périmètre la case périmètre ne doit pas être décochée");
                $this->correct = false;
            }
            if ($this->getVal('type_unite_contenu') != $val['type_unite_contenu']) {
                $this->addToMessage("L'unité contiens d'autres unité, son type d'unité contenu ne doit pas être modifié");
                $this->correct = false;
            }
            if ($this->getVal('type_unite') != $val['type_unite']) {
                $typeParent = $this->f->get_element_by_id('type_unite', $val['type_unite']);
                $typeEnfant = $this->f->get_element_by_id('type_unite', $val['type_unite_contenu']);
                if ($typeParent->getVal('hierarchie') <= $typeEnfant->getVal('hierarchie')) {
                    $this->addToMessage("Le nouveau type doit ne doit pas avoir une hierarchie inférieure à celui qu'il contiens");
                    $this->correct = false;
                }
            }
        }
        // Si une unité est contenu par d'autres unités son type n'est pas modifiable
        if ($this->est_enfant()) {
            if ($this->getVal('type_unite') != $val['type_unite']) {
                $this->addToMessage("L'unité est contenues par d'autres unité, son type ne doit pas être modifié");
                $this->correct = false;
            }
        }

        return $result;
    }


    /**
     * Fait une requête pour récupérer le nombre d'unite enfant lié à
     * l'unité.
     * Si le nombre d'unité enfant est supérieur à 0 alors l'unité est
     * une unité parent. Sinon ce n'est pas le cas.
     *
     * Si la requête échoue ne renvoie rien.
     *
     * @return boolean|void
     */
    protected function est_parent() {
        $sql = sprintf(
            'SELECT
                count(unite_enfant)
            FROM
                %slien_unite
            WHERE
                unite_parent = %d',
            DB_PREFIXE,
            $this->getVal('unite')
        );
        $res = $this->f->db->getOne($sql);
        $this->addToLog(__METHOD__."(): db->getOne(\"".$sql."\");", VERBOSE_MODE);
        if ($this->f->isDatabaseError($res, true)) {
            $this->addToLog(__METHOD__." problèmes sur la requête : ".$res->getDebugInfo().";", DEBUG_MODE);
            $this->addToMessage("Erreur : le nombre d'enfant de l'unité n'a pas pu être récupéré");
            return;
        }
        return $res > 0;
    }

    /**
     * Fait une requête pour récupérer le nombre d'unite parent lié à
     * l'unité.
     * Si le nombre d'unité parent est supérieur à 0 alors l'unité est
     * une unité enfant. Sinon ce n'est pas le cas.
     *
     * Si la requête échoue ne renvoie rien.
     *
     * @return boolean|void
     */
    protected function est_enfant() {
        $sql = sprintf(
            'SELECT
                count(unite_parent)
            FROM
                %slien_unite
            WHERE
                unite_enfant = %d',
            DB_PREFIXE,
            $this->getVal('unite')
        );
        $res = $this->f->db->getOne($sql);
        $this->addToLog(__METHOD__."(): db->getOne(\"".$sql."\");", VERBOSE_MODE);
        if ($this->f->isDatabaseError($res, true)) {
            $this->addToLog(__METHOD__." problèmes sur la requête : ".$res->getDebugInfo().";", DEBUG_MODE);
            $this->addToMessage("Erreur : le nombre de parent de l'unité n'a pas pu être récupéré");
            return;
        }
        return $res > 0;
    }

    /**
     * Vérifie que la valeur passée en paramètre est un entier positif et
     * qu'elle existe dans la base de données.
     * Affiche un message si cette valeur n'existe pas dans la base
     *
     * @param $donneeATester valeur à tester
     * @param string $nomDuChamp nom utilisé dans les messages
     *
     * @return boolean true si la donnée est valide false sinon
     */
    protected function validateur_select_type_unite($donneeATester, $nomDuChamp) {
        if ($result = $this->f->validateur_entier_positif($donneeATester)) {
            // vérification de l'existence dans la base
            $sql = "SELECT 
                        type_unite
                    FROM 
                        ".DB_PREFIXE."type_unite
                    WHERE
                        type_unite = ".$this->f->db->escapeSimple($donneeATester);
            $typeUniteBase = $this->f->db->getOne($sql);
            // si la requête échoue on renvoie false
            if ($this->f->isDatabaseError($typeUniteBase, true)) {
                $class = "error";
                $message = __("Erreur de base de donnees. Contactez votre administrateur.");
                $this->addToMessage($class, $message);
                $result = false;
            }
            if ($result && $typeUniteBase === null) {
                $this->addToMessage("La valeur de ".$nomDuChamp." n'existe pas dans la base");
                $result = false;
            }
        }
        return $result;
    }

    /**
     * validateur du champ type_unite
     */
    public function validate_type_unite($donneeATester) {
        return $this->validateur_select_type_unite($donneeATester, 'type_unite');
    }

    /**
     * validateur du champ type_unite_contenu
     */
    public function validate_type_unite_contenu($donneeATester) {
        return $this->validateur_select_type_unite($donneeATester, 'type_unite_contenu');
    }


    /**
     * Méthode qui effectue les requêtes de configuration des champs.
     *
     * @param object  $form Instance du formulaire.
     * @param integer $maj  Mode du formulaire.
     * @param null    $dnu1 @deprecated Ancienne ressource de base de données.
     * @param null    $dnu2 @deprecated Ancien marqueur de débogage.
     *
     * @return void
     */
    function setSelect(&$form, $maj, &$dnu1 = null, $dnu2 = null) {
        parent::setSelect($form, $maj);
        //En mode modification ou ajout
        if ($maj == 0 || $maj == 1) {
            // Initialise le select en fonction de la valeur du champs type_unite
            $form->setSelect('type_unite_contenu', $this->loadSelect_type_unite_contenu($form, $maj, "type_unite"));
        }
    }

    /**
     * Compose le tableau de paramétrage du select "type_unite_contenu".
     *
     * Ce select liste tout les types d'unités de hiérarchie inférieure
     * à celle du type d'unité
     *
     * @param  object  $form  Formulaire.
     * @param  integer $maj   Mode d'insertion.
     * @param  string  $champ Champ activant le filtre.
     *
     * @return array Tableau de paramétrage du select.
     */
    protected function loadSelect_type_unite_contenu(&$form, $maj, $champ) {
        // Initialisation du tableau de paramétrage du select :
        // - la clé 0 contient le tableau des valeurs,
        // - la clé 1 contient le tableau des labels,
        // - les clés des tableaux doivent faire correspondre le couple valeur/label.
        $contenu = array(
            0 => array('', ),
            1 => array(__('choisir')." ".__("type_unite_contenu"), ),
        );

        // Récupération de l'identifiant du type d'unité :
        // (par ordre de priorité)
        // - si une valeur est postée : c'est le cas lors du rechargement d'un
        //   formulaire et que le select doit être peuplé par rapport aux
        //   données saisies dans le formulaire,
        // - si la valeur est passée en paramètre : c'est le cas lors d'un
        //   appel via le snippet filterselect qui effectue un
        //   $object->setParameter($linkedField, $idx); lors d'un appel ajax
        //   depuis le formulaire (sélection d'un type d'unité contenu via
        //   l'autocomplete qui recharge en ajax la liste des type d'unité),
        // - si la valeur est dans l'enregistrement de l'unité sur laquelle on se
        //   trouve : c'est le cas lors de la première ouverture du formulaire
        //   en modification par exemple.
        $typeParent = "";
        if (isset($_POST[$champ])) {
            $typeParent = $_POST[$champ];
        } elseif ($this->getParameter($champ) != "") {
            $typeParent = $this->getParameter($champ);
        } elseif (isset($form->val[$champ])) {
            $typeParent = $form->val[$champ];
        }

        // Si on a pas le type d'unité alors on ne peut pas définir
        // quelles sont les types d'unités de hiérarchie inférieure
        // On retourne donc le select vide
        if (empty($typeParent)) {
            return $contenu;
        }

        // Récupération de l'instance du type d'unité pour obtenir sa valeur de
        // hiérarchie
        $typeUnite = $this->f->get_inst__om_dbform(array(
            "obj" => "type_unite",
            "idx" => $typeParent
        ));
        $hierarchie = $typeUnite->getVal('hierarchie');


        // Requête sql permettant de trouver les types de hiérarchie inférieure
        // à celle de l'unité parente
        $sql_type_unite_contenu_by_hierarchie_parent =
        " SELECT
            type_unite.type_unite, libelle
        FROM
            ".DB_PREFIXE."type_unite
        WHERE
            hierarchie < ".$hierarchie;

        // Exécution de la requête
        $res = $this->f->db->query($sql_type_unite_contenu_by_hierarchie_parent);
        $this->addToLog(
            __METHOD__."(): db->query(\"".$sql_type_unite_contenu_by_hierarchie_parent."\");",
            VERBOSE_MODE
        );
        $this->f->isDatabaseError($res);

        // Chaque résultat de la requête est ajouté au tableau de paramétrage
        // du select :
        // - la clé 0 contient le tableau des valeurs,
        // - la clé 1 contient le tableau des labels.
        while ($row =& $res->fetchRow(DB_FETCHMODE_ASSOC)) {
            $contenu[0][] = $row['type_unite'];
            $contenu[1][] = $row['libelle'];
        }

        // On retourne le tableau de paramétrage
        return $contenu;
    }


    /**
     * VIEW - view_unite_perimetre.
     *
     * Permet de récupérer et d'afficher le libellé du type d'unité
     * contenu
     *
     * Son instanciation est identique à la fonction formulaire.
     *
     * @return void
     */
    function view_unite_perimetre() {
        // Désactive les logs
        $this->f->disableLog();
        // Initialisation de la variable de retour
        $return = array(
            "type_unite_contenu" => ""
        );
        //
        $postvar = $this->getParameter("postvar");
        // Si la valeur selected est envoyé
        if (!empty($postvar['selected'])) {
            // Instance de la classe type_unite
            $type_unite_contenu = $this->f->get_inst__om_dbform(array(
                "obj" => "type_unite",
                "idx" => $postvar['selected'],
            ));
            $return["type_unite_contenu"] = $type_unite_contenu->getVal('libelle');
            // Affiche tableau json
            echo json_encode($return);
        }
    }


    /**
     * VIEW - view_is_bureau.
     *
     * Ecris un tableau json :
     *      'is_bureau' => $is_bureau  -> booléen indiquant si
     * le type d'unité est un bureau ou pas
     *
     * @return void
     */
    function view_is_bureau() {
        // Il est nécessaire de désactiver les logs car si les modes VERBOSE, EXTRA VERBOSE, etc
        // sont activé, les logs sont affichés en HTML ce qui casse le format json attendu en sortie
        $this->f->disableLog();
        $id_type_unite = $this->f->get_submitted_get_value('type_unite');
        // Si la valeur récupérée est valide alors son comportement (bureau ou pas)
        // est enregistré dans un tableau json sinon un code d'erreur est envoyé
        if (! $this->validate_type_unite($id_type_unite)) {
            // code retour 404 car la valeur du champ du select est invalide donc on ne peut
            // trouver aucun objet avec
            header('HTTP/1.1 404 Not Found');
            return;
        }
        echo json_encode(array(
            'is_bureau' => $this->is_bureau($id_type_unite)
        ));
    }

    /**
     * VIEW - view_code_obligatoire.
     *
     * Ecris un tableau json :
     *      'is_bureau' => $is_bureau  -> booléen indiquant si
     * le type d'unité est un bureau ou pas
     *
     * @return void
     */
    function view_code_obligatoire() {
        // Il est nécessaire de désactiver les logs car si les modes VERBOSE, EXTRA VERBOSE, etc
        // sont activé, les logs sont affichés en HTML ce qui casse le format json attendu en sortie
        $this->f->disableLog();
        $id_type_unite = $this->f->get_submitted_get_value('type_unite');
        if (! $this->validate_type_unite($id_type_unite)) {
            // code retour 404 car la valeur du champ du select est invalide donc on ne peut
            // trouver aucun objet avec
            header('HTTP/1.1 404 Not Found');
            return;
        }
        // Si l'unité est de type bureau de vote alors le libelle prend une '*'
        // pour être signalé comme obligatoire
        if ($this->is_bureau($id_type_unite)) {
            echo json_encode(array(
                'libelle' => 'code unite *'
            ));
            return;
        }
        echo json_encode(array(
            'libelle' => 'code unite'
        ));
    }

    /**
     * Indique si une unité est un bureau en fonction de son type
     * @return boolean
     */
    protected function is_bureau($typeUniteId) {
        // Instance de la classe type_unite permettant d'accéder à l'attribut bureau_vote
        $typeUnite = $this->f->get_inst__om_dbform(array(
            "obj" => "type_unite",
            "idx" => $typeUniteId,
        ));
        $is_bureau = $this->f->boolean_string_to_boolean($typeUnite->getVal('bureau_vote'));
        return $is_bureau;
    }


    /**
     * Liste tous les id des unités contenues si l'unité est un périmètre.
     * L'identifiant de l'unité servant de périmètre fait également partie
     * de la liste.
     *
     * @return array $unitesId
     */
    public function get_all_contained_unites_id() {
        //perimetre est l'unite de saisie dont on cherche les unités contenues
        $perimetre = $this->getVal('unite');
        $unitesId = array($perimetre);
        // Si l'unité est un périmètre, fait la liste des identifiants des unités
        // contenues par ce périmètre
        if ($this->is_perimetre()) {
            //liste des unites à tester pour trouver leurs descendants
            $unitesIdToTest = array($perimetre);
            //unite dont on cherche les descendant
            $currentUnite = array_shift($unitesIdToTest);

            while (! empty($currentUnite)) {
                //recupere toutes les unitesId contenu dans l'unite passée en paramètre
                //et les ajoute à la liste des id des unites contenues
                $listeIdEnfant = $this->get_unite_enfant($currentUnite);
                $unitesId = array_merge($unitesId, $listeIdEnfant);
                $unitesIdToTest = array_merge($unitesIdToTest, $listeIdEnfant);
                $currentUnite = array_shift($unitesIdToTest);
            }
        }
        return $unitesId;
    }

    /**
     * Réupère et fournit la liste des identifiants des unités
     * enfants de l'unité parent passée en paramètre.
     * Seul les enfants directs sont présents dasn cette liste.
     *
     * Par exemple : avec une mairie contenant 2 arrondissements et
     * chacun des arrondissements contiens n bureau. En utilisant, cette
     * méthode avec comme parent la mairie, seul les arrondissements seront
     * présent dans la liste.
     *
     * @param integer $parentId identifiant de l'unité dont on cherche les
     * unités enfant
     * @return array liste des enfants
     */
    public function get_unite_enfant($parentId) {
        //Utilisation de la requête permettant de récupérer les unités
        //enfants d'une unité
        $sql = $this->sqlFindUniteEnfant($parentId);
        $res = $this->db->query($sql);
        $this->addToLog(__METHOD__."(): db->query(\"".$sql."\");", VERBOSE_MODE);
        $this->f->isDatabaseError($res);

        //stockage des résultats dans un tableau
        $listeIdEnfant = array();
        while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
            $listeIdEnfant[] = $row['unite_enfant'];
        }

        //tableau contenant la liste des unités enfants de l'unité passée en paramètre
        return $listeIdEnfant;
    }

    /**
     * Construction de la requête permettant de trouver les unités contenues dans un perimetre donné
     *
     * @param integer $uniteParent identifiant du périmètre
     * @return string requête sql
     */

    protected function sqlFindUniteEnfant($uniteParent) {
        $sqlFindUniteEnfant = "
            SELECT
		        unite_enfant
            FROM
                ".DB_PREFIXE."lien_unite
            WHERE
                unite_parent = '%d'";
                
        return sprintf(
            $sqlFindUniteEnfant,
            $uniteParent
        );
    }

    /**
     * Indique si une unité est un périmètre ou pas
     *
     * @return boolean
     */
    public function is_perimetre() {
        return $this->f->boolean_string_to_boolean($this->getVal('perimetre'));
    }

    /**
     * VIEW - view_import_unites.
     *
     * @return void
     */
    function view_import_unites() {
        $this->checkAccessibility();
        $obj = "unite";
        require_once "../obj/import_specific.class.php";
        $i = new import_specific();
        $i->compute_import_list();
        $i->set_form_action_url($this->getDataSubmit());
        $i->set_form_back_link_url($this->get_back_link("formulaire"));
        if (isset($_POST["submit-csv-import"])) {
            $i->treatment_import($obj);
        }
        $i->display_import_form($obj);
    }

    /**
     *
     *
     * @return string
     */
    function getFormTitle($ent) {
        if ($this->getParameter("maj") == 9) {
            return $ent." -> ".__("import");
        }
        return parent::getFormTitle($ent);
    }

    /**
     * MERGE_FIELDS - Liste des classes *and co*.
     * @var array
     */
    var $merge_fields_and_co_obj = array(
        "canton",
        "circonscription",
        "commune",
        "departement",
    );

    /**
     * Récupère la liste des unités déléguées à un acteur donné.
     *
     * @param int $acteurId Identifiant de l'acteur.
     *
     * @return array|false  Tableau contenant des unités déléguées avec id et label,
     *                     ou false en cas d'erreur de lecture en base.
     */
    public function fetchDelegatedUnites(int $acteurId) {
        $sql = sprintf(
            'SELECT d.unite AS id, u.libelle AS label
            FROM %sdelegation d
            LEFT JOIN %sunite u ON d.unite = u.unite
            WHERE d.acteur = %d
            ORDER BY u.libelle',
            DB_PREFIXE, DB_PREFIXE, $acteurId
        );

        $res = $this->f->db->query($sql);

        if ($this->f->isDatabaseError($res)) {
            echo '<div class="msg-erreur">'.__('Erreur pendant la lecture des délégations.').'</div>';
            return false;
        }

        $out = [];
        while ($r = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
            $out[] = [
                'id'    => $r['id'],
                'label' => $r['id'].' - '.$r['label']
            ];
        }

        return $out;
    }
}
