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

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

/**
 * Définition de la classe 'type_unite'.
 *
 * Cette classe gère les types d'unités électorales (bureaux de vote,
 * arrondissements, secteurs, etc.). Elle hérite de la classe générée
 * type_unite_gen et ajoute la validation de la cohérence hiérarchique
 * et l'exposition JSON.
 */
class type_unite extends type_unite_gen {

    /**
     * Définition des actions disponibles sur la classe.
     *
     * Ajoute les actions JSON permettant d'exposer les données des types
     * d'unités via une API REST :
     * - json_list (997) : liste de tous les types d'unités
     * - json_data (998) : données d'un type d'unité spécifique
     *
     * @return void
     */
    function init_class_actions() {
        parent::init_class_actions();
        // ACTION - 997 - json_list
        // Expose la liste des types d'unités au format JSON
        $this->class_actions[997] = array(
            "identifier" => "json_list",
            "view" => "view_json_list",
            "permission_suffix" => "tab",
        );
        // ACTION - 998 - json_data
        // Expose les données d'un type d'unité au format JSON
        $this->class_actions[998] = array(
            "identifier" => "json_data",
            "view" => "view_json_data",
            "permission_suffix" => "consulter",
        );
    }

    /**
     * SETTER FORM - setLib
     * 
     * @param formulaire $form Instance formulaire.
     * @param integer $maj Identifant numérique de l'action.
     * 
     * @return void
     */
    function setLib(&$form, $maj) {
        //libelle des champs pour éviter les termes techniques
        parent::setLib($form, $maj);
        $form->setLib('type_unite', 'id');
        $form->setLib('bureau_vote', 'bureau de vote');
    }

    /**
     * Vérifie la validité des valeurs en mode CREATE & UPDATE.
     *
     * @param array $val Tableau des valeurs brutes.
     * @param null &$dnu1 @deprecated  Ne pas utiliser.
     * @param null $dnu2 @deprecated  Ne pas utiliser.
     *
     * @return void
     */
    function verifier($val = array(), &$dnu1 = null, $dnu2 = null) {
        parent::verifier($val);
        if ($this->get_action_crud() !== 'create' && (
            !$this->coherence_hierarchie_unite_contenu($val) ||
            !$this->coherence_hierarchie_unite_perimetre($val)
            )) {
            $this->correct = false;
        }
    }

    /**
     * Vérifie si la modification de la hierarchie du type d'unité conserve la
     * cohérence hiérarchique entre les unités parente et les unités quelles contiennent
     * 
     * @param array $val Tableau des valeurs brutes.
     * 
     * @return boolean
     */
    protected function coherence_hierarchie_unite_contenu($val) {
        // On récupére la liste des type d'unites qui sont associées
        // a des unités et qui contiennent le type testé
        $sql = "SELECT
                unite.type_unite
            FROM
                ".DB_PREFIXE."type_unite 
            JOIN
                ".DB_PREFIXE."unite 
            ON
                type_unite.type_unite = unite.type_unite_contenu
            WHERE
                type_unite.type_unite =".$this->getVal('type_unite');
        $res = $this->f->db->query($sql);
        $this->addToLog(__METHOD__."(): db->query(\"".$sql."\");", VERBOSE_MODE);
        $this->f->isDatabaseError($res);
        // Recupére la liste de la hierarchie de ces type d'unités
        $hierarchieParents = array();
        while ($row =& $res->fetchRow(DB_FETCHMODE_ASSOC)) {
            $typeUniteParent = $this->f->get_inst__om_dbform(array(
                "obj" => 'type_unite',
                "idx" => $row['type_unite']
            ));
            $hierarchieParents[] = $typeUniteParent->getVal('hierarchie');
        }
        // Si la liste n'est pas vide alors on a des perimetres qui contiennent des unités
        // du type recherché. La hierarchie d'un perimetre ne peut pas etre superieure ou
        // egale à celle de son parent, si ce n'est pas le cas la saisie n'est pas correcte
        if (!empty($hierarchieParents) && $val['hierarchie'] >= min($hierarchieParents)) {
            $this->addToMessage(
                "Attention pour garder la cohérence des périmètres ".
                "la hiérarchie ne peut pas être supérieure ou égale à ".
                min($hierarchieParents)
            );
            return false;
        }
        return true;
    }

    /**
     * Vérifie si la modification de la hierarchie du type d'unité conserve la
     * cohérence hiérarchique entre les unités enfants et les unités qui les contiennent
     * 
     * @param array $val Tableau des valeurs brutes.
     * 
     * @return boolean
     */
    protected function coherence_hierarchie_unite_perimetre($val) {
        // Récupere la liste de tous les types d'unités qui sont
        // contenu par des unités du type cherché
        $sql = "SELECT
                unite.type_unite_contenu
            FROM
                ".DB_PREFIXE."type_unite 
            LEFT JOIN
                ".DB_PREFIXE."unite 
            ON
                type_unite.type_unite = unite.type_unite
            WHERE
                type_unite.type_unite =".$this->getVal('type_unite');
        $res = $this->f->db->query($sql);
        $this->addToLog(__METHOD__."(): db->query(\"".$sql."\");", VERBOSE_MODE);
        $this->f->isDatabaseError($res);
        // Liste des hierarchies des types des unites contenues
        $hierarchieEnfants = array();
        while ($row =& $res->fetchRow(DB_FETCHMODE_ASSOC)) {
            $typeUniteEnfant = $this->f->get_inst__om_dbform(array(
                "obj" => 'type_unite',
                "idx" => $row['type_unite_contenu']
            ));
            $hierarchieEnfants[] = $typeUniteEnfant->getVal('hierarchie');
        }
        // Si la liste n'est pas vide alors on a des unités qui sont contenues par des unités
        // du type recherché. La hierarchie d'un perimetre ne peut pas etre inférieure ou
        // egale à celle de son enfant, si ce n'est pas le cas la saisie n'est pas correcte
        if (!empty($hierarchieEnfants) && $val['hierarchie'] <= max($hierarchieEnfants)) {
            $this->addToMessage(
                "Attention pour garder la cohérence des périmètres ".
                "la hiérarchie ne peut pas être inférieure ou égale à ".
                max($hierarchieEnfants)
            );
            return false;
        }
        return true;
    }
}
