<?php
/**
 * Ce script contient la définition de la classe *om_widget*.
 *
 * @package openresultat
 * @version SVN : $Id$
 */

require_once PATH_OPENMAIRIE."obj/om_widget.class.php";

/**
 * Définition de la classe *om_widget*.
 */
class om_widget extends om_widget_core {
    public function view_widget__election($content = null) {
        $elections = array();
        $query = sprintf(
            'SELECT to_char(election.date ,\'DD/MM/YYYY\') as election_date, * FROM %1$selection WHERE is_centaine IS NOT TRUE AND workflow NOT LIKE \'Archivage\'',
            DB_PREFIXE
        );
        $res = $this->f->db->query($query);
        $this->f->isDatabaseError($res);
        while ($row = $res->fetchrow(DB_FETCHMODE_ASSOC)) {
            $elections[] = $row;
        }
        if (count($elections) == 0) {
            echo __("Aucune élection en cours.");
            return false;
        }
        $content = "";
        $workflow_icon = array(
            'Paramétrage'=> 'settings-3-line',  
            'Simulation'=> 'compasses-2-line',  
            'Saisie'=> 'edit-line',  
            'Finalisation'=> 'file-check-line',
        );
        $line_template = '
        <a href="%1$s" class="list-group-item list-group-item-action">
            <h4>%2$s
                <small style="display:block">%3$s</small>
            </h4>
            <span class="badge election-step %4$s"><i class="ri-%5$s"></i>%4$s</span>
        </a>
        ';
        $out = '<div class="list-group">';
        foreach ($elections as $key => $value) {
            $out .= sprintf(
                $line_template,
                OM_ROUTE_FORM."&obj=election&action=3&idx=".$value["election"],
                $value["libelle"],
                $value["election_date"],
                $value["workflow"],
                $workflow_icon[$value["workflow"]],

            );
        }
        $out .= '</div>';
        echo $out;
        return false;

    }

    public function view_widget__web($content = null) {
        $contenuWidget = 'Le portail web n\'est pas actif.';
        if ($this->portail_actif()) {
            $contenuWidget = sprintf(
                '<div class="link-web"><a href="%1$s" target="blank" title="Lien externe"><i class="ri-door-open-line"></i><h4>%2$s <i class="ri-external-link-line"></i></h4></a></div>',
                "../web/",
                __("Accéder au portail web de publication des résultats électoraux")
            );
        }
        echo $contenuWidget;
        return false;
    }

    /**
     * Formate la chaîne reçue en un tableau clé=>valeur
     *
     * @param string $content  Contenu brut du champ “arguments” (une ligne par paramètre)
     * @param array  $params   Liste des clés autorisées
     * @return array           Tableau ['clé' => 'valeur', …]
     */
    function get_arguments($content = null, $params = array()) {
        $arguments   = array();
        $params_tmp1 = explode("\n", $content);

        foreach ($params_tmp1 as $value) {
            // chaque ligne doit être de la forme "clé=valeur"
            $parts = explode("=", $value, 2);
            if (count($parts) === 2 && in_array(trim($parts[0]), $params, true)) {
                $arguments[ trim($parts[0]) ] = trim($parts[1]);
            }
        }

        return $arguments;
    }
















// WIDGET DE SAISIE RAPIDE //

    /**
     * Widget de saisie des résultats :
     *   - gère les requêtes AJAX en mode “résultat”
     *   - affiche soit le sélecteur de table, soit le formulaire complet
     */
    public function view_widget__saisie_resultat($content = null) {
        // 1) Gère les requêtes AJAX (s'arrête si une correspondante est trouvée)
        $this->dispatchAjaxRequests('resultat');

        // 2) Si ?listebureau=false, n'affiche que le sélecteur d'élection
        if (!$this->shouldShowWidget($content)) {
            $elections = $this->fetchElections();
            if (empty($elections)) {
                echo '<div class="msg-erreur">'.__('Aucune élection en cours.').'</div>';
                return false;
            }
            return $this->renderTableWidget($elections);
        }

        // 3) Chargement normal : récupère les élections et bureaux, puis affiche le formulaire
        $elections = $this->fetchElections();
        if (empty($elections)) {
            echo '<div class="msg-erreur">'.__('Aucune élection en cours.').'</div>';
            return false;
        }
        $firstE   = array_key_first($elections);
        $bureaux  = $this->fetchAllBureauxForElection($firstE);
        if (empty($bureaux)) {
            echo '<div class="msg-info">'.__('Aucun bureau pour cette élection.').'</div>';
            return false;
        }
        $firstB = $bureaux[0]['id'];
        $idx    = $this->fetchDefaultIdx($firstE, $firstB);

        $this->renderSaisieForm($elections, $bureaux, $idx);
        return false;
    }

    /**
     * Widget de saisie de participation :
     *   - gère les requêtes AJAX en mode “participation”
     *   - affiche le sélecteur seul si shouldShowWidget() est faux
     *   - sinon, charge élections/tranches/unités et affiche le formulaire
     */
    public function view_widget__saisie_participation($content = null)
    {
        // 1) Gère les requêtes AJAX (s'arrête si une correspondante est trouvée)
        $this->dispatchAjaxRequests('participation');

        // 2) Si ?listebureau=false, n'affiche que le sélecteur d'élection (même logique que saisie_resultat)
        if (!$this->shouldShowWidget($content)) {
            $elections = $this->fetchElections();
            if (empty($elections)) {
                echo '<div class="msg-erreur">'.__('Aucune élection en cours.').'</div>';
                return false;
            }
            return $this->renderTableWidget($elections);
        }

        // 3) Chargement normal : récupère élections, tranches et unités (sans bloquer si aucune "autorisation")
        $acteurId  = $this->fetchActeurId();
        $elections = $this->fetchElections();
        if (empty($elections)) {
            echo '<div class="msg-erreur">'.__('Aucune élection en cours.').'</div>';
            return false;
        }

        $firstE   = array_key_first($elections);
        $tranches = $this->fetchTranches($firstE);
        if (empty($tranches)) {
            echo '<div class="msg-info">'.__('Aucune tranche pour cette élection.').'</div>';
            return false;
        }

        // On conserve la récupération des unités, mais on NE BLOQUE PLUS l’affichage si vide
        $unites = $this->fetchDelegatedUnites($acteurId);
        if ($unites === false) {
            $unites = [];
        }

        $firstT = array_key_first($tranches);
        $row    = $this->fetchParticipationElectionRow($firstE, $firstT);
        $idx    = $row['participation_election'] ?? 0;

        // Affiche le formulaire même si $unites est vide : plus de message "Aucune élection autorisé…"
        $this->renderParticipationWidget($elections, $tranches, $unites, $idx);
        return false;
    }



    /**************************************************************************
     * DISPATCH CENTRALISÉ DES REQUÊTES AJAX & FONCTIONS UTILES
     **************************************************************************/

    /**
     * Envoie toutes les requêtes AJAX pour le mode donné et termine si une correspondante est trouvée.
     *
     * @param string $mode 'resultat' ou 'participation'
     */
    private function dispatchAjaxRequests(string $mode): void {
        // vérification commune pour __get_idx
        if ($this->isAjaxGetIdx($mode)) {
            $this->handleAjaxGetIdx($mode);
        }

        if ($mode === 'resultat') {
            if ($this->isAjaxGetTable()) {
                $this->handleAjaxGetTable();
            }
            if ($this->isAjaxGetUnits('bureaux')) {
                $this->handleAjaxGetUnits('bureaux');
            }
            if ($this->isAjaxGetUnits('centaines')) {
                $this->handleAjaxGetUnits('centaines');
            }
        } else {
            if ($this->isAjaxGetUnits('tranches')) {
                $this->handleAjaxGetUnits('tranches');
            }
        }

        // soumission du formulaire
        if ($this->isAjaxSaisie($mode)) {
            $this->handleAjaxSaisieWidget($mode);
        }
    }

    /** @return bool Vrai si c'est un POST avec ?__get_idx et le bon paramètre */
    private function isAjaxGetIdx(string $mode): bool {
        $field = $mode === 'resultat' ? 'bureau' : 'tranche';
        return isset($_GET['__get_idx'])
            && $this->isPost()
            && isset($_POST['election'], $_POST[$field]);
    }

    /** Gère la récupération de l'idx pour résultat ou participation */
    private function handleAjaxGetIdx(string $mode): void {
        $election = (int) $_POST['election'];
        $field    = $mode === 'resultat' ? 'bureau' : 'tranche';
        $row      = $mode === 'resultat'
                    ? $this->fetchElectionUniteRow($election, (int) $_POST[$field])
                    : $this->fetchParticipationElectionRow($election, (int) $_POST[$field]);

        if ($row) {
            $keyName = $mode === 'resultat' ? 'idx' : 'idx';
            $value   = $mode === 'resultat'
                    ? (int)$row['election_unite']
                    : (int)$row['participation_election'];
            $this->sendJson(['ok' => 1, $keyName => $value]);
        }
        $msg = $mode === 'resultat' ? 'Bureau non trouvé' : 'Tranche non trouvée';
        $this->sendJson(['ok' => 0, 'msg' => $msg]);
    }

    /** @return bool Vrai si c'est un POST avec ?__get_table */
    private function isAjaxGetTable(): bool {
        return isset($_GET['__get_table'])
            && $this->isPost()
            && isset($_POST['election']);
    }

    /** Renvoie la "/table/" des unités + libellés + saisies existantes pour le widget de résultat */
    private function handleAjaxGetTable(): void {
        $election = (int)$_POST['election'];
        $out = [];
        $sql = sprintf(
            'SELECT eu.unite AS id, u.libelle AS label, eu.saisie AS saisie, eu.election_unite AS idx
            FROM %selection_unite eu
            JOIN %sunite u ON u.unite = eu.unite
            WHERE eu.election = %d AND u.perimetre = FALSE
            ORDER BY u.libelle',
            DB_PREFIXE, DB_PREFIXE, $election
        );
        $res = $this->f->db->query($sql);
        if (!$this->f->isDatabaseError($res)) {
            while ($r = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
                $out[] = [
                    'id'     => (int)$r['id'],
                    'label'  => $r['label'],
                    'saisie' => $r['saisie'] ?? '',
                    'idx'    => (int)$r['idx'],
                ];
            }
        }
        $this->sendJson(['units' => $out]);
    }

    /**
     * @param string $type 'bureaux'|'centaines'|'tranches'
     * @return bool
     */
    private function isAjaxGetUnits(string $type): bool {
        switch ($type) {
            case 'bureaux':
                return isset($_GET['__get_bureaux']) && $this->isPost() && !empty($_POST['election']);
            case 'centaines':
                return isset($_GET['__get_centaines']) && $this->isPost() && isset($_POST['election']);
            case 'tranches':
                return isset($_GET['__get_tranches']) && $this->isPost() && !empty($_POST['election']);
        }
        return false;
    }

    /** Récupère et renvoie les bureaux / centaines / tranches selon $type */
    private function handleAjaxGetUnits(string $type): void {
        $election = (int)$_POST['election'];
        switch ($type) {
            case 'bureaux':
                $data = $this->fetchAllBureauxForElection($election);
                $this->sendJson(['ok'=>1, 'bureaux'=>$data]);
            case 'centaines':
                $data = $this->fetchCentaines($election);
                $this->sendJson(['ok'=>1, 'centaines'=>$data]);
            case 'tranches':
                $data = $this->fetchTranches($election);
                $this->sendJson(['tranches'=>$data]);
        }
    }

    /** @return bool Vrai si c'est le POST de soumission du formulaire pour le mode donné */
    private function isAjaxSaisie(string $mode): bool {
        $key = $mode === 'resultat' ? '__ajax_saisie_widget_resultat' : '__ajax_saisie_widget';
        return $this->isPost() && isset($_POST[$key]);
    }

    /**
     * Gestionnaire commun pour enregistrer la participation ou le résultat
     *
     * @param string $mode 'participation' ou 'résultat'
     */
    private function handleAjaxSaisieWidget(string $mode): void {
        session_write_close();
        $acteurId = $_SESSION['id_utilisateur']
                ?? ($_SESSION['utilisateur']['id_utilisateur'] ?? 1);
        $election = (int)($_POST['election'] ?? 0);
        $segment  = (int)($_POST[$mode==='participation' ? 'tranche' : 'bureau'] ?? 0);

        // vérifie que idx existe
        $row = $mode==='participation'
            ? $this->fetchParticipationElectionRow($election, $segment)
            : $this->fetchElectionUniteRow($election, $segment);
        if (!$row) {
            $msg = $mode==='participation' ? 'Tranche introuvable.' : 'Bureau introuvable.';
            $this->sendJson(['ok'=>0,'msg'=>$msg]);
        }

        $okCount = 0;
        $errors  = [];
        foreach ($_POST as $key => $val) {
            if (strpos($key, 'valeur_')===0) {
                $id     = (int)str_replace('valeur_','',$key);
                $value  = trim($val);
                $success = ($mode==='participation')
                        ? $this->updateParticipationUnite($id, $value)
                        : $this->updateResultatUnite($id, $value);
                if ($success) {
                    $okCount++;
                } else {
                    $errors[] = "Erreur SQL pour id $id.";
                }
            }
        }
        $this->sendJson([
            'ok'    => empty($errors) ? 1 : 0,
            'count' => $okCount,
            'msg'   => implode(', ', $errors),
        ]);
    }

    /** Envoie une réponse JSON et termine */
    private function sendJson(array $data): void {
        if (ob_get_length()) {
            ob_end_clean();
        }
        header('Content-Type: application/json');
        echo json_encode($data);
        exit;
    }

    private function isPost(): bool {
        return $_SERVER['REQUEST_METHOD'] === 'POST';
    }


    /**************************************************************************
     * GESTION DES DONNÉES & MISES À JOUR
     **************************************************************************/

    /**
     * Retourne la liste des élections éligibles au widget.
     * Seules les élections avec workflow IN ('Simulation','Saisie') sont prises.
     * @param bool $isCentaineOnly Si TRUE, ne prend que les élections "centaine".
     */
    private function fetchElections(bool $isCentaineOnly = false): array
    {
        // Conditions de base : uniquement les workflows autorisés
        $conditions = [
            "workflow IN ('Simulation','Saisie')"
        ];

        // Filtrage "centaine" identique à l'existant
        if ($isCentaineOnly) {
            $conditions[] = "is_centaine = TRUE";
        } else {
            $conditions[] = "(is_centaine IS NULL OR is_centaine != TRUE)";
        }

        // WHERE final
        $where = implode(' AND ', $conditions);

        // Requête
        $sql = sprintf(
            "SELECT election, libelle
            FROM %selection
            WHERE %s
            ORDER BY libelle",
            DB_PREFIXE,
            $where
        );

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

        if (!$this->f->isDatabaseError($res)) {
            while ($r = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
                $out[$r['election']] = $r['libelle'];
            }
        }

        return $out;
    }

    private function fetchCentaines(int $electionId): array {
        $sql = sprintf(
            'SELECT election AS id, libelle AS label
            FROM %selection
            WHERE election_reference = %d
            ORDER BY libelle',
            DB_PREFIXE, $electionId
        );
        $res = $this->f->db->query($sql);
        $out = [];
        if (!$this->f->isDatabaseError($res)) {
            while ($r = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
                $out[] = $r;
            }
        }
        return $out;
    }

    private function fetchTranches(int $electionId): array {
        $sql = sprintf(
            'SELECT pe.tranche, t.libelle
            FROM %sparticipation_election pe
            JOIN %stranche t ON pe.tranche = t.tranche
            WHERE pe.election = %d
            ORDER BY t.ordre',
            DB_PREFIXE, DB_PREFIXE, $electionId
        );
        $res = $this->f->db->query($sql);
        $out = [];
        if (!$this->f->isDatabaseError($res)) {
            while ($r = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
                $out[$r['tranche']] = $r['libelle'];
            }
        }
        return $out;
    }

    private function fetchAllBureauxForElection(int $electionId): array {
        $sql = sprintf(
            'SELECT eu.unite AS id, u.libelle AS label
            FROM %selection_unite eu
            JOIN %sunite u ON u.unite = eu.unite
            WHERE eu.election = %d AND u.perimetre = FALSE
            ORDER BY u.libelle',
            DB_PREFIXE, DB_PREFIXE, $electionId
        );
        $res = $this->f->db->query($sql);
        $out = [];
        if (!$this->f->isDatabaseError($res)) {
            while ($r = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
                $out[] = $r;
            }
        }
        return $out;
    }

    private function fetchDelegatedUnites(int $acteurId) {
        $sql = sprintf(
            'SELECT d.unite AS id, u.libelle AS label
            FROM %sdelegation d
            LEFT JOIN %sunite u ON d.unite = u.unite
            WHERE d.acteur = %d
            ORDER BY u.libelle',
            DB_PREFIXE, DB_PREFIXE, $acteurId
        );
        $res = $this->f->db->query($sql);
        if ($this->f->isDatabaseError($res)) {
            echo '<div class="msg-erreur">'.__('Erreur pendant la lecture des délégations.').'</div>';
            return false;
        }
        $out = [];
        while ($r = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
            $out[] = [
                'id'    => $r['id'],
                'label' => $r['id'].' - '.$r['label']
            ];
        }
        return $out;
    }

    private function fetchElectionUniteRow(int $election, int $bureau): ?array {
        $sql = sprintf(
            'SELECT election_unite FROM %selection_unite WHERE election = %d AND unite = %d',
            DB_PREFIXE, $election, $bureau
        );
        $res = $this->f->db->query($sql);
        return ($res && $res->numRows())
            ? $res->fetchRow(DB_FETCHMODE_ASSOC)
            : null;
    }

    private function fetchParticipationElectionRow(int $election, int $tranche): ?array {
        $sql = sprintf(
            'SELECT participation_election FROM %sparticipation_election WHERE election = %d AND tranche = %d',
            DB_PREFIXE, $election, $tranche
        );
        $res = $this->f->db->query($sql);
        return ($res && $res->numRows())
            ? $res->fetchRow(DB_FETCHMODE_ASSOC)
            : null;
    }

    private function updateParticipationUnite(int $id, int $valeur): bool {
        $sql = sprintf(
            "UPDATE %sparticipation_unite
            SET votant = %d, saisie = TRUE, envoi_aff = FALSE, envoi_web = FALSE, date_derniere_modif = EXTRACT(EPOCH FROM NOW())
            WHERE participation_unite = %d",
            DB_PREFIXE, $valeur, $id
        );
        $q = $this->f->db->query($sql);
        return !$this->f->isDatabaseError($q);
    }

    private function updateResultatUnite(int $id, int $valeur): bool {
        $sql = sprintf(
            "UPDATE %selection_resultat
            SET resultat = %d, saisie = TRUE, envoi_aff = FALSE, envoi_web = FALSE, date_derniere_modif = EXTRACT(EPOCH FROM NOW())
            WHERE election_resultat = %d",
            DB_PREFIXE, $valeur, $id
        );
        $q = $this->f->db->query($sql);
        return !$this->f->isDatabaseError($q);
    }

    private function fetchDefaultIdx(int $election, int $bureau): int {
        $row = $this->fetchElectionUniteRow($election, $bureau);
        return $row['election_unite'] ?? 0;
    }

    private function fetchActeurId(): ?int {
        if (isset($_SESSION['utilisateur']['id_utilisateur'])) {
            return (int)$_SESSION['utilisateur']['id_utilisateur'];
        }
        if (isset($_SESSION['id_utilisateur'])) {
            return (int)$_SESSION['id_utilisateur'];
        }
        if (isset($_SESSION['login']) && $_SESSION['login'] === 'admin') {
            return 1;
        }
        return null;
    }


    /**************************************************************************
     * AFFICHAGE DES VIEWS
     **************************************************************************/

    /** Affiche le widget de sélection d'élection sous forme de tableau */
    private function renderTableWidget(array $elections): void {
        $e_js = json_encode($elections, JSON_HEX_APOS|JSON_UNESCAPED_UNICODE);
        echo '<div class="widget-saisie-table" style="padding:1em;">'
        . '<div style="margin-bottom:1.5em;">'
        . '<label for="tbl-election" style="font-weight:bold;">'.__('Élection').'</label><br>'
        . '<select id="tbl-election" name="election" style="width:100%;max-width:300px;padding:0.4em;margin-top:0.5em;"></select>'
        . '</div>'
        . '<div id="tables-container"></div>'
        . '</div>'
        . '<script>initTableWidget('.$e_js.');</script>';
    }

    /**
     * Affiche le formulaire complet de saisie des résultats.
     *
     * @param array $elections [id=>libellé]
     * @param array $bureaux   [['id'=>…, 'label'=>…],…]
     * @param int   $idx       election_unite par défaut
     */
    private function renderSaisieForm(array $elections, array $bureaux, int $idx): void {
        $e_js = json_encode($elections, JSON_HEX_APOS|JSON_UNESCAPED_UNICODE);
        $b_js = json_encode($bureaux,  JSON_HEX_APOS|JSON_UNESCAPED_UNICODE);
        echo '<div class="widget-saisie-resultats">'
        . '<form id="dashboard-resultat-form" onsubmit="return false;">'
        . '<label for="res-election">'.__('Élection').'</label><br>'
        . '<select id="res-election" name="election">'.implode('', array_map(
                fn($i,$l)=>"<option value=\"".htmlspecialchars($i)."\">".htmlspecialchars($l)."</option>",
                array_keys($elections), $elections
            )).'</select><br><br>'
        . '<label>'.__('Type de saisie').'</label><br>'
        . '<div id="type-container">'
        . '<select id="res-type" name="type"></select>'
        . '<span id="res-type-static" style="display:none;margin-left:0.5em;">'.__('Résultat').'</span>'
        . '</div><br>'
        . '<label for="res-bureau">'.__('Bureau').'</label><br>'
        . '<select id="res-bureau" name="bureau"></select><br><br>'
        . '<button class="saisie-btn" id="lancer-resultat-btn">'.__('SAISIR LES RÉSULTATS').'</button>'
        . '</form></div>'
        . "<script>initResultatWidget({$e_js}, {$b_js}, {$idx});</script>";
    }

    /**
     * Affiche le formulaire de saisie de participation.
     *
     * @param array $elections [id=>libellé]
     * @param array $tranches  [id=>libellé]
     * @param array $unites    [['id'=>…, 'label'=>…],…]
     * @param int   $idx       participation_election par défaut
     */
    private function renderParticipationWidget(array $elections, array $tranches, array $unites, int $idx): void {
        $e_js = json_encode($elections, JSON_HEX_APOS|JSON_UNESCAPED_UNICODE);
        $t_js = json_encode($tranches,    JSON_HEX_APOS|JSON_UNESCAPED_UNICODE);
        $u_js = json_encode($unites,      JSON_HEX_APOS|JSON_UNESCAPED_UNICODE);
        echo '<div class="widget-saisie-shortlinks">'
        . '<form id="dashboard-saisie-form" onsubmit="return false;">'
        . '<label for="widget-election">'.__('Élection').'</label><br>'
        . '<select id="widget-election" name="election">'.implode('', array_map(
                fn($i,$l)=>"<option value=\"".htmlspecialchars($i)."\">".htmlspecialchars($l)."</option>",
                array_keys($elections), $elections
            )).'</select><br><br>'
        . '<label for="widget-tranche">'.__('Horaire').'</label><br>'
        . '<select id="widget-tranche" name="tranche">'.implode('', array_map(
                fn($i,$l)=>"<option value=\"".htmlspecialchars($i)."\">".htmlspecialchars($l)."</option>",
                array_keys($tranches), $tranches
            )).'</select><br><br>'
        . '<button type="submit" class="saisie-btn" id="lancer-saisie-btn">'.__('Saisir la participation').'</button>'
        . '</form></div>'
        . "<script>initParticipationWidget({$e_js}, {$t_js}, {$u_js}, {$idx});</script>";
    }

    /** Vérifie si le widget doit s'afficher ou si l'on doit seulement afficher le sélecteur de table */
    private function shouldShowWidget($content): bool {
        $args = $this->get_arguments($content, ['listebureau']);
        return !(
            isset($args['listebureau'])
            && trim($args['listebureau']) === 'false'
        );
    }

// WIDGET DE SAISIE RAPIDE //














public function view_widget__animation($content = null) {
    $animations = array();

    $query = sprintf(
        'SELECT e1.election as election_id, e1.libelle as election_libelle, animation.libelle as animation_libelle, * 
         FROM %1$sanimation 
         INNER JOIN %1$selection as e1 on animation.election = e1.election 
         LEFT JOIN %1$selection as e2 on e1.election_reference = e2.election 
         WHERE ((e2.workflow IS NULL OR e2.workflow NOT LIKE \'Archivage\') AND e1.workflow NOT LIKE \'Archivage\') 
         ORDER BY e1.date DESC, e1.election, animation.libelle',
        DB_PREFIXE
    );

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

    while ($row = $res->fetchrow(DB_FETCHMODE_ASSOC)) {
        $animations[] = $row;
    }

    if (count($animations) == 0) {
        echo __("Aucune animation en cours.");
        return false;
    }

    $out = "<ul>";
    foreach ($animations as $value) {
        $out .= sprintf(
            '<li><a target="_blank" href="../aff/animation.php?idx=%1$d&identifier=%2$s">%3$s - %4$s</a></li>',
            (int)$value["election_id"],
            htmlspecialchars($value["animation"]),
            htmlspecialchars($value["election_libelle"]),
            htmlspecialchars($value["animation_libelle"])
        );
    }
    $out .= "</ul>";

    echo $out;
    return false;
}




    /**
     * Vérifie si le portail web est actif.
     * La vérification se fait via une requête sql qui récupère le
     * modèle web actif. Si aucun modèle web n'est récupéré c'est que
     * le portail web n'est pas actif.
     *
     * /!\ cette méthode renvoie false en cas d'erreur de base de données
     *
     * @return boolean
     */
    protected function portail_actif() {
        $sql = sprintf(
            'SELECT
                web
            FROM
                %1$sweb
            WHERE
                actif IS TRUE',
            DB_PREFIXE
        );
        $result = $this->f->get_one_result_from_db_query($sql);
        if ($result['code'] == 'KO') {
            return false;
        }
        // Si le portail web est actif on a un résultat si ce n'est pas le cas
        // la requête ne renverra rien
        return ! empty($result['result']);
    }
}
