/**
 * Retourne les saisies de champs extras d'un objet éditorial indiqué
 * 
 * Les saisies sont filtrées, par défaut par l'autorisation de modifier chaque champs extras.
 * Des options peuvent modifier le comportement.
 *
 * @param string $objet 
 *     Type de l'objet éditorial
 * @param int|null $id_objet 
 *     Identifiant de l'objet (si connu) peut servir aux autorisations.
 * @param array $options {
 *     @var string $autoriser 
 *         'voir' ou 'modifier' (par défaut) : type d'autorisation testé, appellera voirextra ou modifierextra…
 *     @var string[] $whitelist
 *         Liste blanche de noms de champs : ces champs seront à afficher, et uniquement eux (modulo l'autorisation sur chaque champ)
 *     @var string[] $blacklist
 *         Liste noire de noms de champs : ces champs ne seront pas affichés (quelque soit l'autorisation sur chaque champ)
 * }
 * @return array 
 *     Liste de saisies, les champs extras sur l'objet indiqué
**/
function cextras_obtenir_saisies_champs_extras($objet, $id_objet = null, $options = array())
{
    $options += array('autoriser' => 'modifier', 'whitelist' => array(), 'blacklist' => array());
    include_spip('cextras_pipelines');
    if ($saisies = champs_extras_objet(table_objet_sql($objet))) {
        // type d'autorisation
        if (!in_array($options['autoriser'], array('voir', 'modifier'))) {
            $options['autoriser'] = 'modifier';
        }
        // listes inclusions et exclusions
        $whitelist = array_unique(array_filter($options['whitelist']));
        $blacklist = array_unique(array_filter($options['blacklist']));
        // Conserver uniquement les saisies souhaitées
        if (count($whitelist)) {
            foreach ($saisies as $i => $saisie) {
                if (empty($saisie['options']['nom']) or !in_array($saisie['options']['nom'], $whitelist)) {
                    unset($saisies[$i]);
                }
            }
        }
        // Enlever les saisies non souhaitées
        if (count($blacklist)) {
            foreach ($saisies as $i => $saisie) {
                if (in_array($saisie['options']['nom'], $blacklist)) {
                    unset($saisies[$i]);
                }
            }
        }
        // filtrer simplement les saisies que la personne en cours peut voir
        $saisies = champs_extras_autorisation($options['autoriser'], $objet, $saisies, array('id_objet' => $id_objet));
        if ($saisies) {
            // pour chaque saisie presente, de type champs extras (hors fieldset et autres) ajouter un flag d'edition
            $saisies = champs_extras_ajouter_drapeau_edition($saisies);
            $valeurs['_saisies'] = $saisies;
        }
    }
    return $saisies;
}
/**
 * Vérification de la validité des champs extras
 *
 * Lorsqu'un formulaire 'editer_xx' se présente, la fonction effectue,
 * pour chaque champs extra les vérifications prévues dans la
 * définition de la saisie, et retourne les éventuelles erreurs rencontrées.
 * 
 * @pipeline formulaire_verifier
 * @param array $flux Données du pipeline
 * @return array      Données du pipeline
**/
function cextras_formulaire_verifier($flux)
{
    $form = $flux['args']['form'];
    if (strncmp($form, 'editer_', 7) !== 0) {
        return $flux;
    }
    $objet = substr($form, 7);
    if ($saisies = champs_extras_objet($table = table_objet_sql($objet))) {
        include_spip('inc/autoriser');
        include_spip('inc/saisies');
        // restreindre les saisies selon les autorisations
        $id_objet = $flux['args']['args'][0];
        // ? vraiment toujours ?
        $saisies = champs_extras_autorisation('modifier', $objet, $saisies, array_merge($flux['args'], array('id' => $id_objet, 'contexte' => array())));
        // nous ne connaissons pas le contexte dans ce pipeline
        // restreindre les vérifications aux saisies enregistrables
        $saisies = champs_extras_saisies_lister_avec_sql($saisies);
        $verifier = charger_fonction('verifier', 'inc', true);
        foreach ($saisies as $saisie) {
            // verifier obligatoire
            $nom = $saisie['options']['nom'];
            if (isset($saisie['options']['obligatoire']) and $saisie['options']['obligatoire'] and !_request($nom)) {
                $flux['data'][$nom] = _T('info_obligatoire');
                // verifier (api) + normalisation
            } elseif ($verifier and isset($saisie['verifier']['type']) and $verif = $saisie['verifier']['type']) {
                $options = isset($saisie['verifier']['options']) ? $saisie['verifier']['options'] : array();
                $normaliser = null;
                $valeur = _request($nom);
                if ($erreur = $verifier($valeur, $verif, $options, $normaliser)) {
                    $flux['data'][$nom] = $erreur;
                    // si une valeur de normalisation a ete transmis, la prendre.
                } elseif (!is_null($normaliser)) {
                    set_request($nom, $normaliser);
                } else {
                    // [FIXME] exceptions connues de vérifications (pour les dates entre autres)
                    // en attendant une meilleure solution !
                    //
                    // Lorsque le champ n'est pas rempli dans le formulaire
                    // alors qu'une normalisation est demandée,
                    // verifier() sort sans indiquer d'erreur (c'est normal).
                    //
                    // Sauf que la donnée alors soumise à SQL sera une chaine vide,
                    // ce qui ne correspond pas toujours à ce qui est attendu.
                    if ((is_string($valeur) and !strlen($valeur) or is_array($valeur) and $saisie['saisie'] == 'date') and isset($options['normaliser']) and $norme = $options['normaliser']) {
                        // Charger la fonction de normalisation théoriquement dans verifier/date
                        // et si on en trouve une, obtenir la valeur normalisée
                        // qui est théoriquement la valeur par défaut, puisque $valeur est vide
                        include_spip("verifier/{$verif}");
                        if ($normaliser = charger_fonction("{$verif}_{$norme}", "normaliser", true)) {
                            $erreur = null;
                            $defaut = $normaliser($valeur, $options, $erreur);
                            if (is_null($erreur)) {
                                set_request($nom, $defaut);
                            } else {
                                // on affecte l'erreur, mais il est probable que
                                // l'utilisateur ne comprenne pas grand chose
                                $flux['data'][$nom] = $erreur;
                            }
                        } else {
                            include_spip('inc/cextras');
                            extras_log("Fonction de normalisation pour {$verif}_{$norme} introuvable");
                        }
                    }
                }
            }
        }
    }
    return $flux;
}