<?php
/**
 * Ce script permet de définir la classe 'import_specific'.
 *
 * @package openresultat
 * @version SVN : $Id: import_specific.class.php 6138 2016-03-09 10:53:39Z nhaye $
 */

require_once PATH_OPENMAIRIE."om_import.class.php";

/**
 * Définition de la classe import.
 *
 * Cette classe étend le module d'import du framework. Ce module permet
 * l'intégration de données dans l'applicatif depuis des fichiers CSV.
 */
class import_specific extends import {

    /**
     *
     */
    var $script_path = "../app/import_specific.php";

    /**
     *
     */
    var $script_extension = ".import_specific.inc.php";

    /**
     * Ligne de travail du tableau en cours de formatage
     */
    var $line;

    /**
     * Table de ligne rejetées à retournées en csv
     */
    var $rejet = array();

    /**
     * Table de ligne rejetées à retournées en csv
     */
    var $line_error = array();

    /**
     *
     */
    public function set_params($params) {
        $this->_params = $params;
    }

    /**
     *
     */
    public function get_params() {
        if (isset($this->_params) === true) {
            return $this->_params;
        }
    }

    /**
     *
     */
    public function set_form_action_url($url) {
        $this->_form_action_url = $url;
    }

    /**
     *
     */
    public function get_form_action_url() {
        if (isset($this->_form_action_url) === true) {
            return $this->_form_action_url;
        }
    }

    /**
     *
     */
    public function set_form_back_link_url($url) {
        $this->_form_back_link_url = $url;
    }

    /**
     *
     */
    public function get_form_back_link_url() {
        if (isset($this->_form_back_link_url) === true) {
            return $this->_form_back_link_url;
        }
    }

    /**
     * Affichage de la liste des imports disponibles.
     *
     * @return void
     */
    function display_import_list() {
        echo '<div id="import-list">';
        // Composition de la liste de liens vers les imports disponibles.
        // En partant de la liste des imports disponibles, on compose une liste
        // d'éléments composés d'une URL, d'un libellé, et de tous les paramètres
        // permettant l'affichage de l'élément comme un élément de liste.
        $list = array();
        foreach ($this->get_import_list() as $key => $value) {
            $list[] = array(
                "href" => $this->script_path."?obj=".$key,
                "title" => $value["title"],
                "class" => "om-prev-icon import-16",
                "id" => "action-import-".$key."-importer",
            );
        }

        $this->f->layout->display_list(
            array(
                "title" => __("choix de l'import"),
                "list" => $list,
            )
        );

        echo "</div>\n";
    }

    /**
     * Affichage du formulaire d'import.
     *
     * Si une méthode d'affichage du formulaire d'import, spécifique à l'objet, existe
     * c'est cette méthode qui est utilisé pour afficher l'import.
     * /!\ Les méthodes spécifique d'affichage du formulaire de l'import doivent être défini
     * de cette façon :
     *   -> display_import_form_obj($obj)
     *
     * @param string $obj Identifiant de l'import.
     *
     * @return void
     */
    function display_import_form($obj) {
        $methodName = 'display_import_form_'.$obj;
        if (method_exists($this, $methodName)) {
            $this->$methodName($obj);
        } else {
            parent::display_import_form($obj);
        }
    }

    /**
     * Affichage du formulaire d'import spécifique à l'import des unités
     *
     * @param string $obj Identifiant de l'import.
     *
     * @return void
     */
    protected function display_import_form_unite($obj) {
        $form_action_url = $this->get_form_action_url();
        if ($form_action_url === null) {
            $form_action_url = $this->script_path."?obj=".$obj;
        }
        $form_back_link_url = $this->get_form_back_link_url();
        if ($form_back_link_url === null) {
            $form_back_link_url = $this->script_path;
        }
        // Paramétrage du formulaire. Il faut d'abordd définir la liste des champs
        // avant de créer une nouvelle instance de la classe formulaire ayant comme
        // attribut cette liste de champs. Ensuite pour chacun de ces champs, leur
        // type, taille, libelle et taille max doivent être défini
        $champs = array("fic1", "separateur", "departement", "commune");

        $form = $this->f->get_inst__om_formulaire(array(
            "validation" => 0,
            "maj" => 0,
            "champs" => $champs,
        ));

        $form->setLib("fic1", "Fichier CSV");
        $form->setLib("separateur", "Separateur");
        $form->setLib("departement", "Departement");
        $form->setLib("commune", "Commune");

        $form->setType("fic1", "upload2");
        $form->setType("separateur", "select");
        $form->setType("departement", "select");
        $form->setType("commune", "select");

        $form->setTaille("fic1", 64);

        $form->setMax("fic1", 30);
        // Restriction sur le champ d'upload
        $params = array(
            "constraint" => array(
                "size_max" => 8,
                "extension" => ".csv;.txt"
            ),
        );
        $form->setSelect("fic1", $params);

        $listeSeparateur = array(
            0 => array(";", ",", ),
            1 => array("; (point-virgule)", ", (virgule)")
        );
        $form->setSelect("separateur", $listeSeparateur);

        $listeDept = $this->get_select('departement');
        $form->setSelect("departement", $listeDept);

        $listeComm = $this->get_select('commune');
        $form->setSelect("commune", $listeComm);

        // Affichage du formulaire
        echo '<div id="form-csv-import" class="formulaire">';
        $this->f->layout->display__form_container__begin(array(
            "action" => $form_action_url,
            'method' => 'post',
            "name" => "f2",
        ));
        $this->f->layout->display__form_controls_container__begin(array(
            "controls" => "top",
        ));
        $this->f->layout->display__form_input_submit(array(
            "name" => "submit-csv-import",
            "value" => __("Importer"),
            "class" => "boutonFormulaire",
        ));
        $this->f->layout->display_lien_retour(array(
            "href" => $form_back_link_url,
        ));
        $this->f->layout->display__form_controls_container__end();
        $form->entete();
        $form->afficher($champs, 0, false, false);
        $form->enpied();
        $this->f->layout->display__form_controls_container__begin(array(
            "controls" => "bottom",
        ));
        $this->f->layout->display__form_input_submit(array(
            "name" => "submit-csv-import",
            "value" => __("Importer"),
            "class" => "boutonFormulaire",
        ));
        $this->f->layout->display_lien_retour(array(
            "href" => $form_back_link_url,
        ));
        $this->f->layout->display__form_controls_container__end();
        $this->f->layout->display__form_container__end();
        echo "</div>\n";
    }

    /**
     *
     * @return string
     */
    function get_select($champs) {
        $select = array(
            0 => array(null),
            1 => array('Choisir '.$champs)
        );

        $sql = sprintf(
            "SELECT
                %s, libelle
            FROM
                ".DB_PREFIXE."%s
            ORDER BY
                libelle ASC",
            $this->f->db->escapeSimple($champs),
            $this->f->db->escapeSimple($champs)
        );

        $resultat = $this->f->db->query($sql);
        $this->f->addToLog(__METHOD__."(): db->query(\"".$sql."\");", VERBOSE_MODE);
        if ($this->f->isDatabaseError($resultat, true)) {
            $this->f->addToLog(__METHOD__." database error:".$resultat->getDebugInfo().";", DEBUG_MODE);
            return $select;
        }
        while ($row = $resultat->fetchRow(DB_FETCHMODE_ASSOC)) {
            $select[0][] = $row[$champs];
            $select[1][] = $row['libelle'];
        }

        return $select;
    }

    /**
     *
     * @return string
     */
    function get_departement_by_id() {
        return "SELECT
                departement, libelle
            FROM
                ".DB_PREFIXE."departement
            WHERE
                departement = <idx>";
    }

    /**
     *
     * @return string
     */
    function get_commune() {
        return "SELECT
                commune, libelle
            FROM
                ".DB_PREFIXE."commune
            WHERE
                commune = <idx>";
    }

    /**
     *
     * @return string
     */
    function get_commune_by_id() {
        return "SELECT
                commune, libelle
            FROM
                ".DB_PREFIXE."commune
            ORDER BY
                libelle ASC";
    }
    /**
     * Affichage du formulaire d'import spécifique à l'import des unités
     *
     * @param string $obj Identifiant de l'import.
     *
     * @return void
     */
    protected function display_import_form_election_unite($obj) {
        $form_action_url = $this->get_form_action_url();
        if ($form_action_url === null) {
            $form_action_url = $this->script_path."?obj=".$obj;
        }
        $form_back_link_url = $this->get_form_back_link_url();
        if ($form_back_link_url === null) {
            $form_back_link_url = $this->script_path;
        }
        // Paramétrage du formulaire. Il faut d'abordd définir la liste des champs
        // avant de créer une nouvelle instance de la classe formulaire ayant comme
        // attribut cette liste de champs. Ensuite pour chacun de ces champs, leur
        // type, taille, libelle et taille max doivent être défini
        $champs = array("fic1", "separateur", "inscrit");

        $form = $this->f->get_inst__om_formulaire(array(
            "validation" => 0,
            "maj" => 0,
            "champs" => $champs,
        ));

        $form->setLib("fic1", "Fichier CSV");
        $form->setLib("separateur", "Separateur");
        $form->setLib("inscrit", "Liste d'inscrit à importer");

        $form->setType("fic1", "upload2");
        $form->setType("separateur", "select");
        $form->setType("inscrit", "select");

        $form->setTaille("fic1", 64);

        $form->setMax("fic1", 30);
        // Restriction sur le champ d'upload
        $params = array(
            "constraint" => array(
                "size_max" => 8,
                "extension" => ".csv;.txt"
            ),
        );
        $form->setSelect("fic1", $params);

        $listeSeparateur = array(
            0 => array(";", ",", ),
            1 => array("; (point-virgule)", ", (virgule)")
        );
        $form->setSelect("separateur", $listeSeparateur);

        $listesImportable = array(
            0 => array("LP", "LP + LCM", "LP + LCE"),
            1 => array("LP", "LP + LCM", "LP + LCE")
        );
        $form->setSelect("inscrit", $listesImportable);

        echo '<div id="form-csv-import" class="formulaire">';
        $this->f->layout->display__form_container__begin(array(
            "action" => $form_action_url,
            'method' => 'post',
            "name" => "f2",
        ));
        $this->f->layout->display__form_controls_container__begin(array(
            "controls" => "top",
        ));
        $this->f->layout->display__form_input_submit(array(
            "name" => "submit-csv-import",
            "value" => __("Importer"),
            "class" => "boutonFormulaire",
        ));
        // Lien retour
        $this->f->layout->display_lien_retour(array(
            "href" => $form_back_link_url,
        ));
        $this->f->layout->display__form_controls_container__end();
        $form->entete();
        $form->afficher($champs, 0, false, false);

        // Légende des champs pour l'import des inscrits
        echo '<div id="legende" class="formulaire">
                LP : Nombre d\'électeurs inscrits en liste principale
                <br>LCM : Nombre d\'électeurs inscrits en liste complémentaire municipale
                <br>LCE : Nombre d\'électeurs inscrits en liste complémentaire européenne
            </div>';

        $form->enpied();
        $this->f->layout->display__form_controls_container__begin(array(
            "controls" => "bottom",
        ));
        $this->f->layout->display__form_input_submit(array(
            "name" => "submit-csv-import",
            "value" => __("Importer"),
            "class" => "boutonFormulaire",
        ));
        // Lien retour
        $this->f->layout->display_lien_retour(array(
            "href" => $form_back_link_url,
        ));
        $this->f->layout->display__form_controls_container__end();
        $this->f->layout->display__form_container__end();
        echo "</div>\n";
    }

    /**
     * Affichage du formulaire d'import spécifique à l'import des unités
     *
     * @param string $obj Identifiant de l'import.
     *
     * @return void
     */
    protected function display_import_form_candidat($obj) {
        $form_action_url = $this->get_form_action_url();
        if ($form_action_url === null) {
            $form_action_url = $this->script_path."?obj=".$obj;
        }
        $form_back_link_url = $this->get_form_back_link_url();
        if ($form_back_link_url === null) {
            $form_back_link_url = $this->script_path;
        }

        // Paramétrage du formulaire. Il faut d'abordd définir la liste des champs
        // avant de créer une nouvelle instance de la classe formulaire ayant comme
        // attribut cette liste de champs. Ensuite pour chacun de ces champs, leur
        // type, taille, libelle et taille max doivent être défini
        $champs = array("fichier", "reference", "code_reference");

        $form = $this->f->get_inst__om_formulaire(array(
            "validation" => 0,
            "maj" => 0,
            "champs" => $champs,
        ));
        // Fichier
        $form->setLib("fichier", "Fichier XML");
        $form->setType("fichier", "upload2");
        $form->setTaille("fichier", 64);
        $form->setMax("fichier", 30);
        // Restriction sur le champ d'upload
        $form->setSelect("fichier", array(
            "constraint" => array(
                "size_max" => 8,
                "extension" => ".xml"
            ),
        ));
        // Référence
        $form->setLib("reference", "Référence");
        $form->setType("reference", "select");
        $form->setTaille("reference", 20);
        $form->setMax("reference", 20);
        $form->setSelect("reference", array(
            "0" => array(
                'bureau',
                'canton',
                'circonscription',
                'commune',
                'departement'
            ),
            "1" => array(
                'bureau',
                'canton',
                'circonscription',
                'commune',
                'département'
            )
        ));
        // Code référence
        $form->setLib("code_reference", "Code");
        $form->setType("code_reference", "text");
        $form->setTaille("code_reference", 64);
        $form->setMax("code_reference", 30);


        echo '<div id="form-csv-import" class="formulaire">';
        $this->f->layout->display__form_container__begin(array(
            "action" => $form_action_url,
            'method' => 'post',
            "name" => "f2",
        ));
        $this->f->layout->display__form_controls_container__begin(array(
            "controls" => "top",
        ));
        $this->f->layout->display__form_input_submit(array(
            "name" => "submit-csv-import",
            "value" => __("Importer"),
            "class" => "boutonFormulaire",
        ));
        // Lien retour
        $this->f->layout->display_lien_retour(array(
            "href" => $form_back_link_url,
        ));
        $this->f->layout->display__form_controls_container__end();
        $form->entete();
        $form->afficher($champs, 0, false, false);
        $form->enpied();
        $this->f->layout->display__form_controls_container__begin(array(
            "controls" => "bottom",
        ));
        $this->f->layout->display__form_input_submit(array(
            "name" => "submit-csv-import",
            "value" => __("Importer"),
            "class" => "boutonFormulaire",
        ));
        // Lien retour
        $this->f->layout->display_lien_retour(array(
            "href" => $form_back_link_url,
        ));
        $this->f->layout->display__form_controls_container__end();
        $this->f->layout->display__form_container__end();
        echo "</div>\n";
    }

    /**
     * Affichage de l'assistant d'import.
     *
     * Si une méthode d'affichage de l'assistant d'import, spécifique à l'objet, existe
     * c'est cette méthode qui est utilisé.
     * /!\ Les méthodes spécifique d'affichage de l'assistant d'import doivent être défini
     * de cette façon :
     *   -> display_import_helper_obj($obj)
     *
     * @param string $obj Identifiant de l'import.
     *
     * @return void
     */
    function display_import_helper($obj) {
        $methodName = 'display_import_helper_'.$obj;
        if (method_exists($this, $methodName)) {
            $this->$methodName($obj);
        } else {
            parent::display_import_helper($obj);
        }
    }

    /**
     * Affichage de l'assistant d'import des unités
     *
     * @param string $obj Identifiant de l'import.
     *
     * @return void
     */
    function display_import_helper_unite($obj) {
        $href = $this->script_path.'?obj='.$obj.'&amp;action=template';
        $this->display_personnalized_import_helper($obj, true, $href);
    }

    /**
     * Affichage de l'assistant d'import personnalisé.
     * Idem à l'assistant d'import sauf qu'il est possible de choisir
     * si le modèle csv doit etre affiché ou pas. Il est également
     * possible de paramétrer l'url du lien vers le telechargement du csv modèle.
     *
     * @param string $obj Identifiant de l'import.
     * @param boolean $csvModele Indique si il doit y avoir un modèle csv ou pas
     * @param string $href lien vers le telechargement du csv modèle
     *
     * @return void
     */
    function display_personnalized_import_helper($obj, $csvModele = true, $href = '') {
        // Récupération du fichier de paramétrage de l'import
        // XXX Faire un accesseur pour vérifier l'existence du fichier
        include $this->import_list[$obj]["path"];

        if (isset($zone) && !isset($fields)) {
            return;
        }

        printf(
            '<fieldset class="cadre ui-corner-all ui-widget-content">
            <legend class="ui-corner-all ui-widget-content ui-state-active">
                Structure du fichier CSV
            </legend>
            <div>'
        );

        // Lien vers le téléchargement d'un fichier CSV modèle
        if ($csvModele) {
            $this->f->layout->display_link(array(
                "href" => $href,
                "title" => __("Télécharger le fichier CSV modèle"),
                "class" => "om-prev-icon reqmo-16",
                "target" => "_blank",
            ));
        }
        echo '</div>';

        $i = 1;
        $htmlTableLine = '';
        foreach ($fields as $key => $field) {
            // Gestion du caractère obligatoire du champ
            (isset($field["notnull"]) && $field["notnull"] == true) ?
                $needed = true : $needed = false;
            // Type
            $type = '';
            if (isset($field["type"])) {
                $type = $field["type"] != 'blob' ? $field["type"] : 'text';
            }
            // Taille
            $size = '';
            if (isset($field["len"])) {
                    $size = !in_array($field["type"], array("blob", "geom")) ? $field["len"] : '';
            }
            // Obligatoire si not null et si aucune valeur par défaut
            $obligatoire = $needed == true && ! isset($field["default"]) ? 'Oui' : '';
            // Défaut
            $defaut = isset($field["default"]) ? '<i>'.$field['default'].'</i>' : '';
            // Vocabulaire
            // Clé étrangère
            $htmlFK = '';
            if (isset($field["fkey"])) {
                $tableName = $field["fkey"]["foreign_table_name"];
                $columnName = $field["fkey"]["foreign_column_name"];
                $fkAlias = '';
                if (isset($field["fkey"]["foreign_key_alias"])
                    && isset($field["fkey"]["foreign_key_alias"]["fields_list"])) {
                    $fkAlias = count($field["fkey"]["foreign_key_alias"]["fields_list"]) > 1 ?
                        '<br>=> Valeurs alternatives possibles : ' :
                        '<br>=> Valeur alternative possible : ';
                    $fkAlias .= implode(", ", $field["fkey"]["foreign_key_alias"]["fields_list"]);
                }

                $htmlFK = sprintf(
                    'Cle etrangere vers :
                    <a href="%s&obj=%s">
                        %s %s
                    </a>
                    %s',
                    OM_ROUTE_TAB,
                    $tableName,
                    $tableName,
                    $columnName,
                    $fkAlias
                );
            }
            // Dates et booléens
            $field_info = '';
            if (isset($field["type"])) {
                switch ($field["type"]) {
                    case 'date':
                        $field_info = 'Format : YYYY-MM-DD';
                        break;
                    case 'bool':
                        $textEtatNul = $needed == false ? "'' pour état null <br/>" : '';
                        $field_info = sprintf(
                            'Format :<br/>
                            %s
                            \'t\', \'true\', \'1\' pour oui <br/>
                            \'f\', \'false\', \'0\' pour non',
                            $textEtatNul
                        );
                        break;
                    default:
                        break;
                }
            }
            $vocabulaire = $htmlFK.$field_info;

            $htmlTableLine .= sprintf(
                '<tr>
                    <td><b>%s</b></td>
                    <td>%s</td>
                    <td>%s (%s)</td>
                    <td>%s</td>
                    <td>%s</td>
                    <td>%s</td>
                </tr>',
                $i,
                $key,
                $type,
                $size,
                $obligatoire,
                $defaut,
                $vocabulaire
            );
            $i++;
        }

        $htmlHelper = sprintf(
            '<table class="table table-condensed table-bordered table-striped" id="structure_csv">
                <thead>
                    <tr>
                        <th>Ordre</th>
                        <th>Champ</th>
                        <th>Type</th>
                        <th>Obligatoire</th>
                        <th>Defaut</th>
                        <th>Vocabulaire</th>
                    </tr>
                </thead>
                <tbody>
                %s
                </tbody>
            </table>
            </fieldset>',
            $htmlTableLine
        );
        echo $htmlHelper;
    }

    /**
     * Traitement d'import.
     *
     * Si une méthode de traitement d'import, spécifique à l'objet, existe
     * c'est cette méthode qui est utilisé pour afficher l'import.
     * /!\ Les méthodes spécifique de traitement de l'import doivent être défini de
     * cette façon :
     *   -> treatment_import_obj($obj)
     *
     * @param string $obj Identifiant de l'import.
     *
     * @return void
     */
    function treatment_import($obj) {
        $functionName = 'treatment_import_'.$obj;
        if (method_exists($this, $functionName)) {
            $this->$functionName($obj);
        } else {
            parent::treatment_import($obj);
        }
    }

    /**
     * Traitement d'import des unités.
     *
     * @param string $obj Identifiant de l'import.
     *
     * @return void
     */
    function treatment_import_unite($obj) {
        $this->personnalized_treatment_import($obj, 'reorganiser_valeur_import_unite');
    }

    /**
     * Traitement d'import des unités.
     *
     * @param string $obj Identifiant de l'import.
     *
     * @return void
     */
    function treatment_import_election_unite($obj) {
        $this->personnalized_treatment_import($obj, 'reorganiser_valeur_import_election_unite');
    }

    /**
     * Traitement d'import des unités.
     *
     * @param string $obj Identifiant de l'import.
     *
     * @return void
     */
    function treatment_import_candidat($obj) {
        // Récupération du chemin d'acès au fichier
        $fichier_tmp = str_replace("tmp|", "", $_POST['fichier']);
        $path = $this->f->storage->storage->temporary_storage->getPath($fichier_tmp);
        // Vérifie l'existence du fichier
        if (empty($path)) {
            $this->f->displayMessage('error', "Vous n'avez pas selectionné de fichier à importer");
            return;
        }
        // Récupère le XML et vérifie sa validité
        // Désactive les logs du XML pour ne pas les afficher dans les logs PHP
        // et gérer l'erreur à la place
        libxml_use_internal_errors(true);
        if(($xml = simplexml_load_file($path)) === false) {
            $this->f->displayMessage('error', "Le fichier n'a pas pu être chargé.");
            libxml_clear_errors();
            return;
        }
        // Réactive les logs
        libxml_use_internal_errors(false);
        // Récupération de la référence et utilisation pour savoir dans quel
        // élément chercher
        $reference = $_POST['reference'];
        $correspondance = array(
            'bureau' => 'cod_bur_vot',
            'canton' => 'cod_cant',
            'circonscription' => 'code_cir_lg',
            'commune' => 'code_com',
            'departement' => 'code_dept'
        );
        // Récupération du code commune recherché
        $code_ref = $_POST['code_reference'];
        // Récupération de l'id de l'élection
        $election = $this->f->get_submitted_get_value('idx');
        $inst_election = $this->f->get_inst__om_dbform(array(
            'obj' => 'election',
            'idx' => $election
        ));
        // Instanciation d'un objet parti_politique
        $inst_parti_politique = $this->f->get_inst__om_dbform(array(
            'obj' => 'parti_politique',
            'idx' => 0
        ));
        // Instanciation d'un objet candidat
        $inst_candidat = $this->f->get_inst__om_dbform(array(
            'obj' => 'candidat',
            'idx' => 0
        ));
        // Instanciation d'un objet election_candidat
        $election_candidat = $this->f->get_inst__om_dbform(array(
            'obj' => 'election_candidat',
            'idx' => 0
        ));
        // Dump de l'objet
        if(empty($xml->election)) {
            $this->f->displayMessage('error', "Le fichier ne contiens aucune élection permettant d\'importer des candidats.");
            return;
        }
        $bureau_vote = $xml->election->bureaux_vote->bureau_vote;
        $found = false;
        $nouveaux_candidats_crees = 0;
        $nouveaux_partis_crees = 0;
        $candidats_associes = 0;
        $candidats_en_erreur = 0;
        // Vérifie si il y a bien des bureaux de vote dont le paramétrage peut être
        // importés et informe l'utilisateur si ce n'est pas le cas.
        $status = 'error';
        $liste_messages = array(
            __('Le fichier ne contiens aucun bureau de vote permettant d\'importer des candidats.')
        );

        if (! empty($bureau_vote)) {
            $status = 'valid';
            $liste_messages = array();
            foreach($bureau_vote as $bureau) {
                if (isset($bureau->{$correspondance[$reference]})
                    && $bureau->{$correspondance[$reference]} == $code_ref) {
                    // Le bureau voulu existe
                    $found = true;
                    // Supprime tous les candidats de l'élection
                    if(! $inst_election->supprimer_candidats_election($election)) {
                        $status = 'warning';
                        $liste_messages[] = __("Les candidats déjà associés à l'élection n'ont pas pu être supprimés.");
                    }
                    // Vérifie que les informations des candidats sont accessibles
                    if (empty($bureau->candidats->cand)) {
                        // Prépare un message d'erreur à destination de l'utilisateur et stop la boucle
                        $status = 'error';
                        $liste_messages[] = __("Les informations des candidats ne sont pas accessibles.");
                        break;
                    }
                    // Récupère ou crée et associe les candidats à l'élection
                    foreach($bureau->candidats->cand as $candidat) {
                        // Création du parti politique si il n'existe pas déjà
                        $ajout_parti_infos = $inst_parti_politique->ajouter_parti_si_non_existant($candidat->cod_nuance->__toString());
                        // Compte le nombre de partis ajoutés
                        if ($ajout_parti_infos['nouvel_ajout']) {
                            $nouveaux_partis_crees++;
                        }

                        // Création du candidat si il n'existe pas déjà
                        $ajout_candidat_infos = $inst_candidat->ajouter_candidat_si_non_existant($candidat->design_can->__toString());
                        // Compte le nombre de candidat ajouté
                        if ($ajout_candidat_infos['nouvel_ajout']) {
                            $nouveaux_candidats_crees++;
                        }

                        // Ajout du candidat à l'élection
                        $valF = array(
                            'election_candidat' => '',
                            'election' => $election,
                            'candidat' => $ajout_candidat_infos['id'],
                            'ordre' => $candidat->no_panneau->__toString(),
                            'prefecture' => $candidat->cod_depot->__toString(),
                            'age_moyen' => null,
                            'siege' => null,
                            'age_moyen_com' => null,
                            'siege_com' => null,
                            'couleur' => null,
                            'photo' => null,
                            'parti_politique' => $ajout_parti_infos['id'],
                            'age_moyen_mep' => null,
                            'siege_mep' => null
                        );
                        if($election_candidat->ajouter($valF) !== true) {
                            $candidats_en_erreur++;
                            $this->f->addToLog("Echec de l'import du candidat. Description : ".var_export($valF, true));
                            $status = 'warning';
                        } else {
                            $candidats_associes++;
                        }
                    }
                    $liste_messages[] = __("Nouveaux partis politique ajoutés : $nouveaux_partis_crees");
                    $liste_messages[] = __("Nouveaux candidats ajoutés : $nouveaux_candidats_crees");
                    $liste_messages[] = __("Candidats associés à l'élection : $candidats_associes");
                    $liste_messages[] = __("Candidats dont l'ajout à échoué : $candidats_en_erreur");
                    break;
                }
            }
            if (!$found)
            {
                $liste_messages[] = __("La référence n'est pas présente dans le fichier");
                $status = 'warning';
            }
        }
        $this->f->displayMessage($status, implode('</br>', $liste_messages));
    }

    /**
     * Traitement d'import personnalisable.
     * Le traitement commence par récupérer les informations issus du fichier
     * csv. Les informations de ce fichier sont ensuite stockée dans un tableau.
     *
     * Ensuite si un nom de méthode a été sélectionné, cette méthode est utilisée
     * pour organiser comme voulu les informations du tableau issu du fichier csv
     * (changer le nom des colonnes, attribuer des valeurs par défaut, etc.)
     *
     * Si aucune méthode n'a été choisi ou si la méthode d'organisation des infos
     * du tableau à réussi son traitement, les données du tableau sont enregistrées
     * dans la BD dans la table définie dans le fichier de paramétrage.
     *
     * /!\ : les méthodes permettant d'organiser les données avant leur envoi
     * à la BD doivent être écrite de cette façon
     *   - protected function maMethode($valF)   ou valF est le tableau des valeurs
     * issus du fichier csv
     *   - elle doivent renvoyer le tableau des valeurs correctement organisé ou
     * false si jamais le traitement à échoué
     *
     * @param string $obj Identifiant de l'import.
     * @param string $methodName Nom de la méthode permettant d'organiser les
     * données
     *
     * @return boolean indique si le traitement à réussi
     */
    function personnalized_treatment_import($obj, $methodName = '') {
        // On vérifie que le formulaire a bien été validé
        if (!isset($_POST['submit-csv-import'])) {
            //
            return false;
        }

        // On récupère les paramètres du formulaire
        $import_id= isset($_POST['import_id']) ? $_POST['import_id'] : '0';
        $separateur=$_POST['separateur'];

        // On vérifie que le fichier a bien été posté et qu'il n'est pas vide
        if (isset($_POST['fic1']) && $_POST['fic1'] == "") {
            //
            $class = "error";
            $message = __("Vous n'avez pas selectionne de fichier a importer.");
            $this->f->displayMessage($class, $message);
            //
            return false;
        }

        // On enlève le préfixe du fichier temporaire
        $fichier_tmp = str_replace("tmp|", "", $_POST['fic1']);
        // On récupère le chemin vers le fichier
        $path = $this->f->storage->storage->temporary_storage->getPath($fichier_tmp);
        // On vérifie que le fichier peut être récupéré
        if (!file_exists($path)) {
            //
            $class = "error";
            $message = __("Le fichier n'existe pas.");
            $this->f->displayMessage($class, $message);
            //
            return false;
        }

        // Configuration par défaut du fichier de paramétrage de l'import
        //
        $table = "";
        // Clé primaire numérique automatique. Si la table dans laquelle les
        // données vont être importées possède une clé primaire numérique
        // associée à une séquence automatique, il faut positionner le nom du
        // champ de la clé primaire dans la variable $id. Attention il se peut
        // que ce paramètre se chevauche avec le critère OBLIGATOIRE. Si ce
        // champ est défini dans $zone et qu'il est obligatoire et qu'il est
        // en $id, les valeurs du fichier CSV seront ignorées.
        $id = "";
        //
        $verrou = 1; // =0 pas de mise a jour de la base / =1 mise a jour
        //
        $fic_rejet = 1; // =0 pas de fichier pour relance / =1 fichier relance traitement
        //
        $ligne1 = 1; // = 1 : 1ere ligne contient nom des champs / o sinon
        //
        $encodages = array("UTF-8", "ASCII", "Windows-1252", "ISO-8859-15", "ISO-8859-1");

        // Récupération du fichier de paramétrage de l'import
        // XXX Faire un accesseur pour vérifier l'existence du fichier
        include $this->import_list[$obj]["path"];

        // On ouvre le fichier en lecture
        $fichier = fopen($path, "r");

        // Initialisation des variables
        $cpt = array(
            "total" => 0,
            "rejet" => 0,
            "insert" => 0,
            "firstline" => 0,
            "empty" => 0,
        );
        $rejet = "";

        // Boucle sur chaque ligne du fichier
        while (!feof($fichier)) {
            // Incrementation du compteur de lignes
            $cpt['total']++;
            // Logger
            $this->f->addToLog(__METHOD__."(): LINE ".$cpt['total'], EXTRA_VERBOSE_MODE);
            // On définit si on se trouve sur la ligne titre
            $firstline = ($cpt['total'] == 1 && $ligne1 == 1 ? true : false);
            // On définit le marqueur correct à true
            $correct = true;
            //
            $valF = array();
            $msg = "";

            // Récupération de la ligne suivante dans le fichier
            $contenu = fgetcsv($fichier, 4096, $separateur);

            //
            $this->f->addToLog(__METHOD__."(): LINE ".$cpt['total']." - contenu = ".print_r($contenu, true), EXTRA_VERBOSE_MODE);
            // Si la ligne a plus d'un champ et que le premier champ n'est pas vide
            if (is_array($contenu) && count($contenu) > 1 && $contenu[0] != "") { // enregistrement vide (RC à la fin)
                //
                if ($firstline == true) {
                    //
                    $cpt['firstline']++;
                    // Logger
                    $this->f->addToLog(__METHOD__."(): LINE ".$cpt['total']." - firstline", EXTRA_VERBOSE_MODE);
                    // Récupération des clés du tableau des valeurs correspondants aux entêtes
                    // des colonnes du csv
                    // Dans certain csv il y a un caractère spécial en début de colonne qui fait
                    // buguer la recherche du nom. Si ce caractère existe on le supprime et les
                    // " en trop aussi pour ne garder que le nom de la colonne
                    $csvKeys = $contenu;
                    array_walk(
                        $csvKeys,
                        function (&$nomColonne) {
                            $nomColonne = str_replace('﻿', '', $nomColonne);
                            $nomColonne = str_replace('"', '', $nomColonne);
                            $nomColonne = trim($nomColonne);
                        }
                    );
                } else {
                    if (isset($csvKeys) && ! empty($csvKeys) && is_array($csvKeys)) {
                        $val = array_combine($csvKeys, $contenu);
                    }
                    // NG
                    if (isset($fields)) {
                        // On boucle sur chaque champ défini dans le fichier
                        // de configuration de l'import pour récupérer la
                        // valeur à importer dans la base pour ce champ
                        foreach ($fields as $key => $field) {
                            // Cas ou plusieurs colonne différentes peuvent contenir l'information d'un
                            // champ.
                            if (isset($field['colonnesName']) && isset($val)) {
                                foreach ($field['colonnesName'] as $colonne) {
                                    if (array_key_exists($colonne, $val)) {
                                        $valF[$key][$colonne] = $val[$colonne];
                                    }
                                }
                                // Si aucun résultats n'a été trouvé et que le champ est obligatoire
                                // c'est qu'il manque des infos dans le csv
                                if (! isset($valF[$key]) && (isset($field['notnull']) && $field['notnull'] == '1')) {
                                    // On rejette l'enregistrement
                                    $correct = false;
                                    // Raison du rejet à ajouter dans le fichier rejet
                                    $msg = "La colonne contenant les informations concernant le ".$key." n'existe pas";
                                    // Logger
                                    $this->f->addToLog(__METHOD__."(): REJET => ".$msg, EXTRA_VERBOSE_MODE);
                                }
                            } else {
                                //
                                $key_num = array_search($key, $csvKeys, true);
                                
                                if ($key_num === false &&
                                    array_key_exists('facultatif', $field) && $field['facultatif']
                                ) {
                                    break;
                                } elseif ($key_num === false || !isset($contenu[$key_num])) {
                                    $valF[$key] = -1;
                                    // On rejette l'enregistrement
                                    $correct = false;
                                    // Raison du rejet à ajouter dans le fichier rejet
                                    $msg = __("nombre de colonnes incohérent")." : la colonne ".$key_num." n'existe pas";
                                    // Logger
                                    $this->f->addToLog(__METHOD__."(): REJET => ".$msg, EXTRA_VERBOSE_MODE);
                                } else {
                                    // Suppression des espaces superflus
                                    $valF[$key] = trim($contenu[$key_num]);
                                    // Traitement de l'encodage
                                    $valF[$key] = iconv(mb_detect_encoding($valF[$key], $encodages), "UTF-8", $valF[$key]);
                                    // la chaine de texte 'null' représente la valeur null
                                    if (strtolower($valF[$key]) === "null") {
                                        $valF[$key] = null;
                                    }
                                }
    
                                // Logger
                                $this->f->addToLog(__METHOD__."(): LINE ".$cpt['total']." - champ '".$key."' = '".$valF[$key]."'", EXTRA_VERBOSE_MODE);
    
                                // ----------------------------------------------------
                                // Gestion des valeurs par défaut lors de la
                                // transmission d'une valeur vide ou nulle
                                // ----------------------------------------------------
                                // Si le paramétrage est défini correctement et que la
                                // valeur transmise est vide ou nulle
                                if (isset($field["type"]) && isset($field["notnull"])
                                    && $valF[$key] !== '0'
                                    && (empty($valF[$key]) || is_null($valF[$key]))) {
                                    // Si une valeur par défaut est proposée dans la paramétrage
                                    if (isset($field["default"])) {
                                        // On affecte la valeur par défaut
                                        $valF[$key] = $field["default"];
                                    // Si le champ est de type entier et qu'il n'est pas
                                    // obligatoire
                                    } elseif ($field["type"] == "int"
                                              && $field["notnull"] == false) {
                                        // On affecte null afin de ne pas initialiser
                                        // un champs entier avec une chaine vide ce qui
                                        // provoquerait une erreur de base de données
                                        $valF[$key] = null;
    
                                    // Si le champ est de type date et qu'il n'est pas
                                    // obligatoire
                                    } elseif ($field["type"] == "date"
                                              && $field["notnull"] == false) {
                                        // On affecte null afin de ne pas initialiser
                                        // un champs date avec une chaine vide ce qui
                                        // provoquerait une erreur de base de données
                                        $valF[$key] = null;
    
                                    // Si le champ est de type booléen et qu'il n'est pas
                                    // obligatoire
                                    } elseif ($field["type"] == "bool"
                                              && $field["notnull"] == false) {
                                        // XXX Vérifier pourquoi la valeur null
                                        // provoque une erreur de base de données
                                        $valF[$key] = null;
    
                                    // Si le champ est de type string et qu'il n'est pas
                                    // obligatoire et que ce champ est une clé étrangère
                                    } elseif ($field["type"] == "string"
                                              && $field["notnull"] == false
                                              && isset($field["fkey"])) {
                                        // On affecte null car une chaine vide serait
                                        // considérait comme une clé primaire de l'autre
                                        // table ce qui provoquerait une erreur de base
                                        //  de données
                                        $valF[$key] = null;
    
                                    // Si le champ est de type geom et qu'il n'est pas
                                    // obligatoire
                                    } elseif ($field["type"] == "geom"
                                              && $field["notnull"] == false) {
                                        // On enlève le champ de l'enregistrement
                                        unset($valF[$key]);
                                    }
                                }
    
                                // ----------------------------------------------------
                                // Vérification du caractère obligatoire d'un champ
                                // ----------------------------------------------------
                                if (isset($field["notnull"]) && $field["notnull"] == true
                                    && (empty($valF[$key]) || is_null($valF[$key])) && $valF[$key] != '0') {
                                    // On rejette l'enregistrement
                                    $correct = false;
                                    // Raison du rejet à ajouter dans le fichier rejet
                                    $msg = __("champ obligatoire vide")." : ".$key." = ".$valF[$key];
                                    // Logger
                                    $this->f->addToLog(__METHOD__."(): REJET => ".$msg, EXTRA_VERBOSE_MODE);
                                }
    
                                // ----------------------------------------------------
                                // Vérification de la taille des string
                                // ----------------------------------------------------
                                if (isset($field["type"]) && $field["type"] == "string"
                                    && strlen($valF[$key]) > $field["len"]) {
                                    // On rejette l'enregistrement
                                    $correct = false;
                                    // Raison du rejet à ajouter dans le fichier rejet
                                    $msg = __("valeur trop longue pour le champ")." : ".$key."(".$field["len"].") = ".$valF[$key];
                                    // Logger
                                    $this->f->addToLog(__METHOD__."(): REJET => ".$msg, EXTRA_VERBOSE_MODE);
                                }
    
                                // ----------------------------------------------------
                                // Gestion du critère EXIST
                                // ----------------------------------------------------
                                // Ce critère permet de vérifier si la valeur fournie
                                // existe bien dans la table liée (clé étrangère).
                                // Exemple du paramétrage de ce critère :
                                //   $exist = array(
                                //     "champ1" => 1, // Ce champ est lié et doit exister
                                //     "champ2" => 0, // Ce champ n'est pas lié
                                //   );
                                // Par défaut si le critère n'est pas paramétré, on
                                // considère que le champ n'est pas lié.
                                // Comportement : si la valeur du champ en question
                                // dans le fichier CSV est vide alors on rejette
                                // l'enregistrement
                                // ----------------------------------------------------
                                if (isset($field["fkey"]) && !empty($valF[$key])) {
                                    // Logger
                                    $this->f->addToLog(__METHOD__."(): LINE ".$cpt['total']." - champ '".$key."' - EXIST", EXTRA_VERBOSE_MODE);
                                    // Si le champ recherché est sensé être de type entier et est n'est pas numeric
                                    if (isset($field["type"]) && $field["type"] = "int"
                                        && !is_numeric($valF[$key])
                                        && isset($field["fkey"]["foreign_key_alias"])) {
                                        $sql = str_replace("<SEARCH>", $valF[$key], $field["fkey"]["foreign_key_alias"]["query"]);
                                        $res = $this->f->db->getOne($sql);
                                        if (!is_null($res) && !$this->f->isDatabaseError($res, true)) {
                                            $valF[$key] = $res;
                                        } else {
                                            // On rejette l'enregistrement
                                            $correct = false;
                                            // Raison du rejet à ajouter dans le fichier rejet
                                            $msg = __("cle secondaire inexistante")." : ".$key." = ".$valF[$key]." / ";
                                            // Logger
                                            $this->f->addToLog(__METHOD__."(): REJET => ".$msg, EXTRA_VERBOSE_MODE);
                                        }
                                    } else {
                                        //
                                        $sql = $field["fkey"]["sql_exist"].$valF[$key];
                                        if (strrpos($field["fkey"]["sql_exist"], "'") === strlen($field["fkey"]["sql_exist"])-strlen("'")) {
                                            $sql .= "'";
                                        }
                                        //
                                        $res = $this->f->db->getOne($sql);
                                        // Logger
                                        $this->f->addToLog(__METHOD__."(): db->getone(\"".$sql."\");", VERBOSE_MODE);
                                        // Si le résultat de la requête ne renvoi aucune valeur ou
                                        // une erreur de base de données alors on rejette l'enregistrement
                                        if (is_null($res) || $this->f->isDatabaseError($res, true)) {
                                            // On rejette l'enregistrement
                                            $correct = false;
                                            // Raison du rejet à ajouter dans le fichier rejet
                                            $msg = __("cle secondaire inexistante")." : ".$key." = ".$valF[$key]." / ";
                                            // Logger
                                            $this->f->addToLog(__METHOD__."(): REJET => ".$msg, EXTRA_VERBOSE_MODE);
                                        }
                                    }
                                }
                            }
                        }
                    // OG
                    } elseif (isset($zone)) {
                        // On boucle sur chaque champ définit dans le fichier
                        // de configuration de l'import pour récupérer la
                        // valeur à importer dans la base pour ce champ
                        foreach (array_keys($zone) as $champ) {
                            // Logger
                            $this->f->addToLog(__METHOD__."(): LINE ".$cpt['total']." - champ '".$champ."'", EXTRA_VERBOSE_MODE);

                            // ----------------------------------------------------
                            // Gestion du critère DEFAUT
                            // ----------------------------------------------------
                            if ($zone[$champ] == "") { // valeur par defaut
                                //
                                $valF[$champ] = ""; // eviter le not null value
                                //
                                if (!isset($defaut[$champ])) {
                                    $defaut[$champ] = "";
                                }
                                $valF[$champ] = $defaut[$champ];
                            } else {
                                if (isset($contenu[$zone[$champ]])) {
                                    $valF[$champ] = $contenu[$zone[$champ]];
                                } else {
                                    // On rejette l'enregistrement
                                    $correct = false;
                                    // Raison du rejet à ajouter dans le fichier rejet
                                    $msg = __("nombre de colonnes incohérent")." : la colonne ".$champ." n'existe pas dans le fichier";
                                    // Logger
                                    $this->f->addToLog(__METHOD__."(): REJET => ".$msg, EXTRA_VERBOSE_MODE);
                                }
                            }

                            // ----------------------------------------------------
                            // Gestion du critère OBLIGATOIRE
                            // ----------------------------------------------------
                            // Ce critère permet de vérifier, avant de faire une
                            // requête d'insertion, que la valeur fournie est
                            // correcte. Exemple du paramétrage de ce critère :
                            //   $obligatoire = array(
                            //     "champ1" => 1, // Ce champ est obligatoire
                            //     "champ2" => 0, // Ce champ n'est pas obligatoire
                            //   );
                            // Par défaut si le critère n'est pas paramétré, on
                            // considère que le champ n'est pas obligatoire.
                            // Comportement : si la valeur du champ en question
                            // dans le fichier CSV est vide ou null alors on
                            // rejette l'enregistrement.
                            // ----------------------------------------------------
                            if (isset($obligatoire[$champ])
                                && $obligatoire[$champ] == 1
                                && (empty($valF[$champ]) || is_null($valF[$champ]))) {
                                // On rejette l'enregistrement
                                $correct = false;
                                // Raison du rejet à ajouter dans le fichier rejet
                                $msg = __("champ obligatoire vide")." : ".$champ." = ".$valF[$champ];
                                // Logger
                                $this->f->addToLog(__METHOD__."(): REJET => ".$msg, EXTRA_VERBOSE_MODE);
                            } elseif (!isset($obligatoire[$champ])) {
                                // Par défaut on indique que le champ n'est pas obligatoire
                                $obligatoire[$champ] = 0;
                            }

                            // ----------------------------------------------------
                            // Gestion du critère EXIST
                            // ----------------------------------------------------
                            // Ce critère permet de vérifier si la valeur fournie
                            // existe bien dans la table liée (clé étrangère).
                            // Exemple du paramétrage de ce critère :
                            //   $exist = array(
                            //     "champ1" => 1, // Ce champ est lié et doit exister
                            //     "champ2" => 0, // Ce champ n'est pas lié
                            //   );
                            // Par défaut si le critère n'est pas paramétré, on
                            // considère que le champ n'est pas lié.
                            // Comportement : si la valeur du champ en question
                            // dans le fichier CSV est vide alors on rejette
                            // l'enregistrement
                            // ----------------------------------------------------
                            if (isset($exist[$champ])
                                && $exist[$champ] == 1
                                && !empty($valF[$champ])) {
                                // Logger
                                $this->f->addToLog(__METHOD__."(): LINE ".$cpt['total']." - champ '".$champ."' - EXIST", EXTRA_VERBOSE_MODE);
                                //
                                $sql = $sql_exist[$champ].$valF[$champ];
                                if (strrpos($sql_exist[$champ], "'") === strlen($sql_exist[$champ])-strlen("'")) {
                                    $sql .= "'";
                                }
                                //
                                $res = $this->f->db->getOne($sql);
                                // Logger
                                $this->f->addToLog(__METHOD__."(): db->getone(\"".$sql."\");", VERBOSE_MODE);
                                // Si le résultat de la requête ne renvoi aucune valeur ou
                                // une erreur de base de données alors on rejette l'enregistrement
                                if (is_null($res) || $this->f->isDatabaseError($res, true)) {
                                    // On rejette l'enregistrement
                                    $correct = false;
                                    // Raison du rejet à ajouter dans le fichier rejet
                                    $msg = __("cle secondaire inexistante")." : ".$champ." = ".$valF[$champ];
                                    // Logger
                                    $this->f->addToLog(__METHOD__."(): REJET => ".$msg, EXTRA_VERBOSE_MODE);
                                }
                            } elseif (!isset($exist[$champ])) {
                                // Par défaut on indique que le champ n'est pas lié
                                $exist[$champ] = 0;
                            }
                        }
                    }

                    // Méthode permettant de re-organiser le tableau des valeurs afin de :
                    //  - donner les bons nom aux attributs
                    //  - re-ordonner les valeurs
                    //  - ajouter des valeurs non défini dans l'import
                    //  - etc.
                    // La méthode doit renvoyé le nouveau tableau des valeurs si le traitement
                    // a reussi et false sinon.
                    // Cela permet de définir si l'enregistrement doit être fait ou pas
                    // Si la méthode n'existe pas le traitement par défaut est effectué
                    if ($correct == true) {
                        if (method_exists($this, $methodName)) {
                            $valF = $this->$methodName($valF);
                            if (! is_array($valF)) {
                                $msg = $valF;
                                $correct = false;
                            }
                        }
                    }

                    // Insertion de la ligne dans la base de donnees si la table est renseignée
                    // Si la table n'est pas renseigné on ne crée pas de nouvelle ligne mais
                    // si le traitement a été correctement effectué alors la ligne est considéré
                    // comme importée
                    if ($correct == true && empty($table)) {
                        $cpt["insert"]++;
                    } elseif ($correct == true && ! empty($table)) {
                        // On désactive l'auto-commit
                        $this->f->db->autoCommit(false);
                        //
                        $this->f->addToLog(__METHOD__."(): import_id =>".$import_id, EXTRA_VERBOSE_MODE);
                        if ($id != "" and $import_id == '0') {
                            // Si on n'importe pas l'Id on doit le récupérer de la séquence
                            $res = $this->f->db->nextId($table);
                            // Logger
                            $this->f->addToLog(__METHOD__."(): db->nextId(\"".$table."\");", VERBOSE_MODE);
                            //
                            if ($this->f->isDatabaseError($res, true)) {
                                // On rejette l'enregistrement
                                $correct = false;
                                // Raison du rejet à ajouter dans le fichier rejet
                                $msg = $res->getMessage();
                                // Logger
                                $this->f->addToLog(__METHOD__."(): REJET => ".$msg, EXTRA_VERBOSE_MODE);
                            } else {
                                $valF[$id] = $res;
                            }
                        } elseif ($id != "" and $import_id != '0') {
                            // Si on récupère l'Id on doit mettre à jour la séquence si nécessaire
                            // Récupération de l'Id max
                            $resmax = $this->f->db->getCol('SELECT max('.$id.') FROM '.$table);
                            if ($this->f->isDatabaseError($resmax, true) === true) {
                                $this->f->addToLog(__METHOD__."(): ERREUR => ".$resmax, VERBOSE_MODE);
                            }
                            while (intval($valF[$id]) > intval($resmax)) {
                                $resmax = $this->f->db->nextId($table);
                                // Logger
                                $this->f->addToLog(__METHOD__."(): db->nextId(\"".$table."\"); ->".$resmax, VERBOSE_MODE);
                            }
                        }
                        // Exécution de la requête
                        $res = $this->f->db->autoExecute($table, $valF, DB_AUTOQUERY_INSERT);
                        // Logger
                        $this->f->addToLog(__METHOD__."(): db->autoExecute(\"".$table."\", ".print_r($valF, true).", DB_AUTOQUERY_INSERT);", VERBOSE_MODE);
                        //
                        if ($this->f->isDatabaseError($res, true)) {
                            //
                            $this->f->db->rollback();
                            // On rejette l'enregistrement
                            $correct = false;
                            // Raison du rejet à ajouter dans le fichier rejet
                            $msg = $res->getMessage();
                            // Logger
                            $this->f->addToLog(__METHOD__."(): REJET => ".$msg, EXTRA_VERBOSE_MODE);
                        } else {
                            //
                            if ($verrou == 1) {
                                // Commit de la transaction
                                $this->f->db->commit();
                            } else {
                                $this->f->db->rollback();
                            }
                            //
                            $cpt["insert"]++;
                        }
                    }
                }
                // Si il y a une erreur sur la ligne alors on constitue un fichier
                // de rejet que l'utilisateur corrigera
                if ($correct == false || $firstline == true) {
                    // On recompose la ligne avec les separateurs
                    $ligne = "";
                    if (isset($fields)) {
                        foreach ($fields as $key => $field) {
                            $key_num = array_search($key, array_keys($fields));
                            if (!isset($contenu[$key_num])) {
                                $ligne .= $separateur;
                            } elseif ($field["type"] == "string" or $field["type"] == "blob") {
                                $ligne .= '"'.$contenu[$key_num].'"'.$separateur;
                            } else {
                                $ligne .= $contenu[$key_num].$separateur;
                            }
                        }
                    }
                    // On ajoute une colonne erreur sur la premiere ligne
                    if ($firstline == true) {
                        $ligne .= "rejet";
                    } else {
                        $cpt["rejet"]++;
                        $ligne .= '"'.$msg.'"';
                    }
                    // Ajout du caractere de fin de ligne
                    $rejet .= $ligne."\n";
                }
            } else {
                $cpt["empty"]++;
            }
        }

        // Fermeture du fichier
        fclose($fichier);

        /**
         * Affichage du message de résultat de l'import
         */
        // Composition du message résultat
        $message = __("Resultat de l'import")."<br/>";
        $message .= $cpt["total"]." ".__("ligne(s) dans le fichier dont :")."<br/>";
        $message .= " - ".$cpt["firstline"]." ".__("ligne(s) d'entete")."<br/>";
        $message .= " - ".$cpt["insert"]." ".__("ligne(s) importee(s)")."<br/>";
        $message .= " - ".$cpt["rejet"]." ".__("ligne(s) rejetee(s)")."<br/>";
        $message .= " - ".$cpt["empty"]." ".__("ligne(s) vide(s)")."<br/>";
        //
        if ($fic_rejet == 1 && $cpt["rejet"] != 0) {
            //
            $class = "error";
            // Composition du fichier de rejet
            $rejet = substr($rejet, 0, strlen($rejet) - 1);
            $metadata = array(
                "filename" => "import_".$obj."_".date("Ymd_Gis")."_rejet.csv",
                "size" => strlen($rejet),
                "mimetype" => "application/vnd.ms-excel",
            );
            $uid = $this->f->storage->create_temporary($rejet, $metadata);
            // Enclenchement de la tamporisation de sortie
            ob_start();
            //
            $this->f->layout->display_link(array(
                "href" => OM_ROUTE_FORM."&snippet=file&amp;uid=".$uid."&amp;mode=temporary",
                "title" => __("Télécharger le fichier CSV rejet"),
                "class" => "om-prev-icon reqmo-16",
                "target" => "_blank",
            ));
            // Affecte le contenu courant du tampon de sortie au message puis l'efface
            $message .= ob_get_clean();
        } else {
            //
            $class = "ok";
        }
        //
        $this->f->displayMessage($class, $message);
    }

    /**
     * Enregistre les valeurs récupérer lors de l'import dans la base
     * de données
     *
     * @param array $valF tableau des valeurs à reorganiser
     * @return mixed boolean false si le traitement à echoué ou le tableau
     * des valeurs modifié si il a reussi
     */
    protected function reorganiser_valeur_import_unite($valF) {
        $valUnite = array(
            'unite' => null,
            'id_reu' => null,
            'libelle' => null,
            'type_unite' => null,
            'ordre' => null,
            'adresse1' => null,
            'adresse2' => null,
            'cp' => null,
            'ville' => null,
            'code_unite' => null,
            'canton' => null,
            'circonscription' => null,
            'commune' => ! empty($_POST['commune']) ? $_POST['commune'] : null,
            'departement' => ! empty($_POST['departement']) ? $_POST['departement'] : null
        );

        // Récupération de l'identifiant du bureau.
        // /!\ le nom de la colonne id est mal récupéré sur les csv d'élire et est
        //     noté "Id" (avec les guillemets inclus).
        //     TODO : corriger ce problème
        //
        // Il y a deux nom de colonne possible pour l'identifiant du bureau :
        //    - Id
        //    - Identifiant du bureau
        // Vérifie si une valeur a été enregistré pour le premier nom possible.
        // Si c'est le cas, vérifie qu'il s'agit bien d'un entier. Si ce n'est pas un
        // entier un message d'erreur informant l'utilisateur est renvoyé.
        // Si c'est le cas, vérifie si cet entier est différent de 0. Si oui, la valeur
        // est associée au champ id_reu. Si non, c'est qu'on importe une unité qui n'est
        // pas un BV et qui donc n'a pas d'id dans le reu. Dans ce cas, on garde le champ
        // id_reu null.
        //
        // Si le premier nom de colonne ne correspond pas le même traitement est effectué
        // Avec le second.
        //
        // Si aucun des deux noms ne correspond alors un message d'erreur est renvoyé pour
        // informer l'utilisateur que cette colonne est obligatoire
        if (array_key_exists('Id', $valF)) {
            if (array_key_exists("﻿\"Id\"", $valF['Id']) || array_key_exists("Id", $valF['Id'])) {
                $idReu = array_key_exists("﻿\"Id\"", $valF['Id']) ?
                    $valF['Id']["﻿\"Id\""] :
                    $valF['Id']["Id"];
    
                if (! is_numeric($idReu)) {
                    $msg = 'L\'identifiant du bureau doit être un nombre';
                    return $msg;
                }
    
                $valUnite['id_reu'] = $idReu != 0 ? $idReu : null;
            } elseif (array_key_exists('Identifiant du bureau', $valF['Id'])) {
    
                if (! is_numeric($valF['Id']["Identifiant du bureau"])) {
                    $msg = 'L\'identifiant du bureau doit être un nombre';
                    return $msg;
                }
    
                $valUnite['id_reu'] = $valF['Id']['Identifiant du bureau'] != 0 ?
                    $valF['Id']['Identifiant du bureau'] :
                    null;
            } else {
                $msg = 'L\'identifiant du bureau doit être renseigné';
                return $msg;
            }
        }

        // Récupération du code du bureau.
        if (array_key_exists('Code', $valF['Code']) && ! empty($valF['Code']['Code'])) {
            $valUnite['ordre'] = $valF['Code']['Code'];
            $valUnite['code_unite'] = $valF['Code']['Code'];
        } elseif (array_key_exists('Code du bureau', $valF['Code'])
            && ! empty($valF['Code']['Code du bureau'])
        ) {
            $valUnite['ordre'] = $valF['Code']['Code du bureau'];
            $valUnite['code_unite'] = $valF['Code']['Code du bureau'];
        } else {
            $msg = 'Le code du bureau doit être renseigné';
            return $msg;
        }
        // Vérifie que le code unité importé est unique
        $inst_unite = $this->f->get_inst__om_dbform(array(
            'obj' => 'unite',
            'idx' => ']'
        ));
        if (! $inst_unite->is_code_unite_unique($valUnite['code_unite'])) {
            $msg = 'Le code de l\'unité doit être unique';
            return $msg;
        }

        // Récupération de son libellé
        if (array_key_exists('Libellé', $valF['Libelle']) && ! empty($valF['Libelle']['Libellé'])) {
            $valUnite['libelle'] = $valF['Libelle']['Libellé'];
        } elseif (array_key_exists('Libellé du bureau', $valF['Libelle'])
            && ! empty($valF['Libelle']['Libellé du bureau'])
        ) {
            $valUnite['libelle'] = $valF['Libelle']['Libellé du bureau'];
        } else {
            $msg = 'Le libelle de l\'unité doit être renseigné';
            return $msg;
        }

        // Récupération du code canton et de son libellé.
        // Il existe 2 cas :
        //    1- Le libellé et le code sont contenus dans le même champ. Il y a donc
        //       une seule colonne du csv qui contiens l'information et qu'il va
        //       falloir redécouper
        //    2- Le libellé et le code sont séparés. Il y a donc 2 colonnes qui contiennent
        //       l'information et il faut récupérer l'information des deux colonnes
        $valCanton = array();
        if (array_key_exists('Canton', $valF['Canton']) &&
            ! empty($valF['Canton']['Canton'])
        ) {
            $valCanton = $this->format_canton_circonscription($valF['Canton']['Canton']);
            $valCanton = array(
                'canton' => null,
                'libelle' => $valCanton['libelle'],
                'prefecture' => 0,
                'code' => $valCanton['code']
            );
        } elseif (array_key_exists('Code du canton', $valF['Canton']) &&
            ! empty($valF['Canton']['Code du canton'])
        ) {
            // Si il n'y a pas de libelle c'est le code qui sert de libelle par défaut
            $libelle = ! empty($valF['Canton']['Libellé du canton']) ?
                $valF['Canton']['Libellé du canton'] :
                $valF['Canton']['Code du canton'];
            $valCanton = array(
                'canton' => null,
                'libelle' => $libelle,
                'prefecture' => 0,
                'code' => $valF['Canton']['Code du canton']
            );
        }

        // Vérifie dans la base de données si il existe déjà un canton ayant ce code.
        // Si c'est le cas le champ canton de l'unité prend la valeur de l'identifiant récupéré.
        // Sinon un nouveau canton est crée et on récupére son identifiant
        if (! empty($valCanton)) {
            $idCanton = $this->get_identifiant_canton_circonscription('canton', $valCanton['code']);
            if ($idCanton ===  false) {
                return 'DB Error : la récupération de l\'identifiant du canton a échouée';
            } elseif (is_numeric($idCanton)) {
                $valUnite['canton'] = $idCanton;
            } elseif (empty($idCanton) && $idCanton !== false) {
                $canton = $this->f->get_element_by_id('canton', ']');
                if (! $canton->ajouter($valCanton)) {
                    $msg = 'La création du canton a échouée';
                    return $msg;
                }
                $valUnite['canton'] = $canton->valF['canton'];
            }
        }

        // Même principe avec la circonscription
        // Récupération du code canton et de son libellé.
        // Il existe 2 cas :
        //    1- Le libellé et le code sont contenus dans le même champ. Il y a donc
        //       une seule colonne du csv qui contiens l'information et qu'il va
        //       falloir redécouper
        //    2- Le libellé et le code sont séparés. Il y a donc 2 colonnes qui contiennent
        //       l'information et il faut récupérer l'information des deux colonnes
        $valCirconscription = array();
        if (array_key_exists('Circonscription législative', $valF['Circonscription']) &&
            ! empty($valF['Circonscription']['Circonscription législative'])
        ) {
            $valCirconscription = $this->format_canton_circonscription(
                $valF['Circonscription']['Circonscription législative']
            );
            $valCirconscription = array(
                'circonscription' => null,
                'libelle' => $valCirconscription['libelle'],
                'prefecture' => 0,
                'code' => $valCirconscription['code']
            );
        } elseif (array_key_exists('Code de la circonscription législative', $valF['Circonscription']) &&
            ! empty($valF['Circonscription']['Code de la circonscription législative'])
        ) {
            // Si il n'y a pas de libelle c'est le code qui sert de libelle par défaut
            $libelle = ! empty($valF['Circonscription']['Libellé de la circonscription législative']) ?
                $valF['Circonscription']['Libellé de la circonscription législative'] :
                $valF['Circonscription']['Code de la circonscription législative'];
            $valCirconscription = array(
                'circonscription' => null,
                'libelle' => $libelle,
                'prefecture' => 0,
                'code' => $valF['Circonscription']['Code de la circonscription législative']
            );
        }

        // Vérifie dans la base de données si il existe déjà une circonscription ayant ce code.
        // Si c'est le cas le champ circonscription de l'unité prend la valeur de l'identifiant récupéré.
        // Sinon une nouvelle circonscription est crée et on récupére son identifiant
        if (! empty($valCirconscription)) {
            $idCirconscription = $this->get_identifiant_canton_circonscription('circonscription', $valCirconscription['code']);
            if ($idCirconscription === false) {
                return 'DB Error : la récupération de l\'identifiant de la circonscription a échouée';
            } elseif (is_numeric($idCirconscription)) {
                $valUnite['circonscription'] = $idCirconscription;
            } elseif (empty($idCirconscription) && $idCirconscription !== false) {
                $circonscription = $this->f->get_element_by_id('circonscription', ']');
                if (! $circonscription->ajouter($valCirconscription)) {
                    $msg = 'La création de la circonscription a échouée';
                    return $msg;
                }
                $valUnite['circonscription'] = $circonscription->valF['circonscription'];
            }
        }


        // Récupération de l'adresse
        foreach ($valF['Adresse'] as $key => $value) {
            switch ($key) {
                case 'Adresse':
                    // Gestion de l'adresse lorsque l'adresse n'est composé
                    // que d'un seul champ contre 4 dans openrésultat (adresse 1 et 2,  cp et ville)
                    // IL faut donc redécouper l'adresse pour la séparer entre les différents champs
                    $adresseDecoupe = $this->decoupe_adresse($value);
                    foreach ($adresseDecoupe as $champ => $valeur) {
                        $valUnite[$champ] = $valeur;
                    }
                    break;
                case 'Code postal':
                    // Evite d'écraser le code postal si un code à été récupéré dans le champ
                    // adresse et que le champ code postal n'est pas rempli
                    $valUnite['cp'] = ! empty($value) ? $value : $valUnite['cp'];
                    break;
                case 'Commune':
                    $valUnite['ville'] = $value;
                    break;
                default:
                    // TODO : A améliorer pour pouvoir gérer au mieux le remplissage de l'adresse
                    if (strlen($valUnite['adresse1'].' '.$value) < 100) {
                        $valUnite['adresse1'] .= $value;
                    } elseif (strlen($valUnite['adresse2'].' '.$value) < 100) {
                        $valUnite['adresse2'] .= $value;
                    }
                    break;
            }
        }

        // Récupération et affectation du type d'unité
        if (array_key_exists('Type', $valF) && ! empty($valF['Type'])) {
            $valUnite['type_unite'] = $valF['Type'];
        } elseif (! empty($this->f->getParameter('id_type_unite_bureau_de_vote'))) {
            $valUnite['type_unite'] = $this->f->getParameter('id_type_unite_bureau_de_vote');
        } else {
            $msg = 'Erreur : le type d\'unité à ajouter n\'a pas été paramétré';
            return $msg;
        }
        
        return $valUnite;
    }

    /**
     * Récupère les valeurs issus du csv.
     * Pour chaque ligne du csv, effectue une requête pour récupèrer
     * l'unité de l'élection ayant le même identifiant de bureau issus
     * d'ELIRE
     *
     * @param array $valF tableau des valeurs à reorganiser
     * @return mixed boolean false si le traitement à echoué ou le tableau
     * des valeurs modifié si il a reussi
     */
    protected function reorganiser_valeur_import_election_unite($valF) {
        // Récupère l'identifiant de l'élection
        $params = $this->get_params();
        if (array_key_exists("election_id", $params) === true
            && $params["election_id"] != "") {
            //
            $electionId = $params["election_id"];
        } else {
            $this->f->displayMessage("Error", 'Erreur : pas d\'élection associée à \'import');
            return 'Erreur : pas d\'élection associée à \'import';
        }

        // Récupération des listes à utiliser pour obtenir le nombre d'inscrit
        $listesInscrit = isset($_POST['inscrit']) ? $_POST['inscrit'] : false;
        if ($listesInscrit === false) {
            $this->f->displayMessage("Error", 'Erreur : la liste de récupération des inscrits n\'est pas définie');
            return 'Erreur : la liste de récupération des inscrits n\'est pas définie';
        }

        // Récupération de l'identifiant du bureau ou du code du bureau si l'identifiant
        // n'est pas renseigné
        // /!\ le nom de la colonne id est mal récupéré sur les csv d'élire et est
        //     noté "Id" (avec les guillemets inclus).
        //     TODO : corriger ce problème
        if (array_key_exists('Id', $valF)) {
            if (array_key_exists("﻿\"Id\"", $valF['Id']) && ! empty($valF['Id']["﻿\"Id\""])) {
                $idReu = $valF['Id']["﻿\"Id\""];
            } elseif (array_key_exists('Id', $valF['Id'])
                && ! empty($valF['Id']['Id'])
            ) {
                $idReu = $valF['Id']['Id'];
            } elseif (array_key_exists('Identifiant du bureau', $valF['Id'])
                && ! empty($valF['Id']['Identifiant du bureau'])
            ) {
                $idReu = $valF['Id']['Identifiant du bureau'];
            } else {
                $msg = 'L\'identifiant du bureau doit être renseigné';
                return $msg;
            }
        } elseif (array_key_exists('Code', $valF)) {
            // Si il n'y a pas d'id a récupérer c'est le code du bureau qui doit être utilisé
            if (array_key_exists('Code', $valF['Code']) && ! empty($valF['Code']['Code'])) {
                $code = $valF['Code']['Code'];
            } elseif (array_key_exists('Code du bureau', $valF['Code'])
                && ! empty($valF['Code']['Code du bureau'])
            ) {
                $code = $valF['Code']['Code du bureau'];
            } else {
                $msg = 'Le code du bureau doit être renseigné';
                return $msg;
            }
        } else {
            $msg = __('Le code du bureau ou son identifiant issus du reu doit obligatoirement être renseigné');
            return $msg;
        }
        

        // Récupération de l'identifiant de l'unité rattachée a l'élection et sur laquelle
        // on va ajouter le nombre d'inscrit.
        // Si l'id du reu est renseigné c'est cette id qui servira a récupérer l'unité.
        // Sinon c'est le code de l'unité qui permettra de le récupérer
        if (isset($idReu)) {
            $idElectionUnite = $this->get_identifiant_election_unite_using_reu_id($electionId, $idReu);
        } elseif (isset($code)) {
            $idElectionUnite = $this->get_identifiant_election_unite_using_code_unite($electionId, $code);
        } else {
            $msg = __('Erreur lors de la récupération du code ou de l\'identifiant du bureau');
            return $msg;
        }

        // Calcul des inscrits
        $LP = null;
        if (array_key_exists("Nombre d'électeurs inscrits en LP", $valF['Inscrits']) &&
            ! empty($valF['Inscrits']["Nombre d'électeurs inscrits en LP"])
        ) {
            $LP = $valF['Inscrits']["Nombre d'électeurs inscrits en LP"];
        } elseif (array_key_exists("Nombre d'électeurs inscrits en liste principale", $valF['Inscrits'])
            && ! empty($valF['Inscrits']["Nombre d'électeurs inscrits en liste principale"])
        ) {
            $LP = $valF['Inscrits']["Nombre d'électeurs inscrits en liste principale"];
        }

        if (array_key_exists("Nombre d'électeurs inscrits en LCM", $valF['Inscrits']) &&
            ! empty($valF['Inscrits']["Nombre d'électeurs inscrits en LCM"])
        ) {
            $LCM = $valF['Inscrits']["Nombre d'électeurs inscrits en LCM"];
        } elseif (array_key_exists("Nombre d'électeurs inscrits en liste complémentaire municipale", $valF['Inscrits'])
            && ! empty($valF['Inscrits']["Nombre d'électeurs inscrits en liste complémentaire municipale"])
        ) {
            $LCM = $valF['Inscrits']["Nombre d'électeurs inscrits en liste complémentaire municipale"];
        }

        if (array_key_exists("Nombre d'électeurs inscrits en LCE", $valF['Inscrits']) &&
            ! empty($valF['Inscrits']["Nombre d'électeurs inscrits en LCE"])
        ) {
            $LCE = $valF['Inscrits']["Nombre d'électeurs inscrits en LCE"];
        } elseif (array_key_exists("Nombre d'électeurs inscrits en liste complémentaire européenne", $valF['Inscrits'])
            && ! empty($valF['Inscrits']["Nombre d'électeurs inscrits en liste complémentaire européenne"])
        ) {
            $LCE = $valF['Inscrits']["Nombre d'électeurs inscrits en liste complémentaire européenne"];
        }

        switch ($listesInscrit) {
            case "LP" :
                $inscrit = $LP;
                break;
            case "LP + LCM" :
                $inscrit = $LP;
                if (isset($LCM) && is_numeric($LCM)) {
                    $inscrit = $LP + $LCM;
                }
                break;
            case "LP + LCE" :
                $inscrit = $LP;
                if (isset($LCE) && is_numeric($LCE)) {
                    $inscrit = $LP + $LCE;
                }
                break;
            default:
                return 'Cas non existant : le nombre d\'inscrit ne peut pas être calculé';
        }

        if (! empty($idElectionUnite)) {
            $modifier = $this->f->modifier_element_BD_by_id(
                'election_unite',
                $idElectionUnite,
                array('inscrit' => $inscrit)
            );
            if ($modifier ===  false) {
                return 'ERREUR BD : les inscrits n\'ont pas été importé';
            }
            $electionUnite = $this->f->get_element_by_id('election_unite', $idElectionUnite);
            $electionUnite->maj_resultats_perimetres();
        } elseif ($idElectionUnite === false) {
            return 'ERREUR BD : erreur lors de la récupération de l\'unité';
        }

        return $valF;
    }

    /**
     * Prend une adresse et la découpe en quatre partie :
     *   - adresse 1 -> numero + voie + ville
     *   - adresse 2 (complément d'adresse)
     *   - code postal
     * Renvoie l'adresse sous la forme d'un tableau
     *
     * @param string adresse
     * @return array adresse découpée
     */
    protected function decoupe_adresse($adresse) {
        $adresseDecoupe = array(
            'adresse1' => '',
            'adresse2' => '',
            'cp' => '',
            'ville' => ''
        );
        // Suppression du pays
        $adresse = preg_replace('{france}i', '', $adresse);
        // Suppression des espaces superflu
        $adresse = trim($adresse);

        // Récupération du code postal
        $resultats = array();
        if (preg_match('{[0-9]{5}}', $adresse, $resultats)) {
            $adresseDecoupe['cp'] = $resultats[0];
            $adresse = str_replace($resultats[0], '', $adresse);
            $adresse = trim($adresse);
        }

        // Aprés avoir supprimer le pays et le code postal il ne doit rester dans
        // la chaine que le numero de voie, la voie, le complément d'adresse et la ville
        $tailleMaxAdresse = 100;
        $adresseDecoupe['adresse1'] = $adresse;
        if (strlen($adresse) > $tailleMaxAdresse) {
            $decoupe = explode(
                "\n",
                wordwrap($adresse, $tailleMaxAdresse, "\n")
            );
            $adresse = $decoupe[0];
            $complement = isset($decoupe[1]) ? $decoupe[1] : '';
            $adresseDecoupe['adresse1'] = $adresse;
            $adresseDecoupe['adresse2'] = $complement;
        }
        return $adresseDecoupe;
    }

    /**
     * Découpe la chaîne de caractère reçue en entrée de cette façon :
     *   - code    -> code prefecture canton/circonscription
     *   - libelle     -> libelle canton/circonscription
     *
     * Les formes possibles pour le code sont :
     *      - 09507 ou 9507
     *      - 95-07 ou 095-07
     *      - 95 07 ou 095 07
     *      - 07 ou 7
     *
     * Si il y a un "-" entre le code et le libellé il est supprimé. Si il n'y a
     * pas de libelle, c'est le code récupéré qui servira de libellé
     *
     * @param string $champsCsv information issue du csv
     * @return array code et libelle canton/circonscription
     */
    protected function format_canton_circonscription($champsCsv) {
        // Récupération du code du canton/circ les formes possibles son
        $resultat = array();
        $champsCsv = trim($champsCsv);
        if (preg_match("{[0-9]{4,5}}i", $champsCsv, $resultat)) {
            $code = $resultat[0];
        } elseif (preg_match("{[0-9]{2,3}-[0-9]{2}}i", $champsCsv, $resultat)) {
            $code = $resultat[0];
        } elseif (preg_match("{[0-9]{2,3} [0-9]{2}}i", $champsCsv, $resultat)) {
            $code = $resultat[0];
        } elseif (preg_match("{[0-9]{1,2}}i", $champsCsv, $resultat)) {
            $code = $resultat[0];
        } else {
            // Le code étant obligatoire si il n'a pas pu être récupéré le traitement
            // ne doit pas continuer
            $this->f->addToMessage('Le code n\'a pas pu être récupéré');
            return false;
        }

        // Suppression du code de la chaine de caractère
        $champsCsv = str_replace($resultat[0], '', $champsCsv);
        $champsCsv = trim($champsCsv);

        // Récupération du libellé en supprimant le "-" en début de ligne si il y en a un
        $libelle = preg_replace("{^-}", '', $champsCsv);
        $libelle = trim($libelle);
        if (empty($libelle)) {
            $libelle = $code;
        }

        // Stockage des résultats dans un tableau
        $valeursChamps = array(
            'code' => $code,
            'libelle' => $libelle
        );
        return $valeursChamps;
    }

    /**
     * Requête sql permettant de récupérer l'identifiant d'un canton/ une circonscription
     * à l'aide de son code préfecture.
     * Renvoie l'identifiant si il/elle existe dans la base et null sinon.
     * En cas d'erreur renvoie false.
     *
     * /!\ Recherche le même code donc si un canton à un code de format "07" en base et
     *     "9507" dans le fichier, il ne pourra pas être trouvé
     *
     * @param string $table nom de la table de l'objet
     * @param array tableau associatif contenant le nom de l'attribut et la valeur à chercher
     * @return mixed integer -> identifiant de l'objet | null si l'objet n'existe pas
     */
    protected function get_identifiant_canton_circonscription($table, $code) {
        if (empty($code)) {
            return false;
        }
        // Construction de la requête pour récupérer l'identifiant de l'objet dans la table
        // donnée. Ne marche que si la colonne d'identifiant et la table ont le même nom
        // La recherche s'effectue à l'aide du code du canton
        $sql = sprintf(
            "SELECT
                %s.%s
            FROM
                %s%s
            WHERE
                code LIKE '%s'",
            $this->f->db->escapeSimple($table),
            $this->f->db->escapeSimple($table),
            $this->f->db->escapeSimple(DB_PREFIXE),
            $this->f->db->escapeSimple($table),
            $this->f->db->escapeSimple($code)
        );
        $resultat = $this->f->db->getOne($sql);
        $this->f->addToLog(__METHOD__."(): db->getOne(\"".$sql."\");", VERBOSE_MODE);
        if ($this->f->isDatabaseError($resultat, true)) {
            $this->f->addToLog(__METHOD__." database error:".$resultat->getDebugInfo().";", DEBUG_MODE);
            return false;
        }
        return $resultat;
    }

    /**
     * Effectue une requête sql permettant de récupérer l'identifiant d'une unité rattaché
     * à une élection en utilisant l'identifiant de cette élection et le code de l'unité
     *
     * Renvoie l'identifiant si il/elle existe dans la base et null sinon.
     * En cas d'erreur renvoie false.
     *
     *
     * @param integer identifiant de l'élection
     * @param integer code du bureau
     * @return boolean|integer identifiant de l'objet ou false en cas d'erreur
     */
    protected function get_identifiant_election_unite_using_code_unite($idElection, $codeUnite) {
        if (empty($idElection) || empty($codeUnite)) {
            return false;
        }

        $sql = sprintf(
            'SELECT
                election_unite
            FROM
                %1$selection_unite
                INNER JOIN %1$sunite ON election_unite.unite = unite.unite
            WHERE
                election = %2$d AND
                code_unite = \'%3$s\'',
            $this->f->db->escapeSimple(DB_PREFIXE),
            $this->f->db->escapeSimple($idElection),
            $this->f->db->escapeSimple($codeUnite)
        );
        $resultat = $this->f->db->getOne($sql);
        $this->f->addToLog(__METHOD__."(): db->getOne(\"".$sql."\");", VERBOSE_MODE);
        if ($this->f->isDatabaseError($resultat, true)) {
            $this->f->addToLog(__METHOD__." database error:".$resultat->getDebugInfo().";", DEBUG_MODE);
            return false;
        }
        return $resultat;
    }

    /**
     * Requête sql permettant de récupérer l'identifiant d'une unité rattaché
     * à l'élection.
     * Renvoie l'identifiant si il/elle existe dans la base et null sinon.
     * En cas d'erreur renvoie false.
     *
     *
     * @param integer identifiant de l'élection
     * @param integer identifiant du bureau issu du REU
     * @return boolean|integer identifiant de l'objet ou false en cas d'erreur
     */
    protected function get_identifiant_election_unite_using_reu_id($idElection, $idReu) {
        if (empty($idElection) || empty($idReu)) {
            return false;
        }

        $sql = sprintf(
            "SELECT
                election_unite
            FROM
                %selection_unite
                INNER JOIN %sunite ON election_unite.unite = unite.unite
            WHERE
                election = %d AND
                id_reu = %d",
            $this->f->db->escapeSimple(DB_PREFIXE),
            $this->f->db->escapeSimple(DB_PREFIXE),
            $this->f->db->escapeSimple($idElection),
            $this->f->db->escapeSimple($idReu)
        );
        $resultat = $this->f->db->getOne($sql);
        $this->f->addToLog(__METHOD__."(): db->getOne(\"".$sql."\");", VERBOSE_MODE);
        if ($this->f->isDatabaseError($resultat, true)) {
            $this->f->addToLog(__METHOD__." database error:".$resultat->getDebugInfo().";", DEBUG_MODE);
            return false;
        }
        return $resultat;
    }
}
