Hello,

Dans les derniers plugins que j'ai réalisé j'ai pris l'habitude de créer
des API d'objets pour lire un objet et pour répertorier une liste d'objets
éventuellement filtrée.
Au fil du temps j'ai donc écrit les mêmes fonctions à quelques
améliorations près, mais le code est rigoureusement le même dans le fond.
L'objet de ce mail est de discuter de la première fonction soit
objet_lire().

J'ai donc écrit une fonction générique objet_lire() qui permet de lire un
objet par son id ou par un autre identifiant unique (comme prefixe pour les
plugins) et d'utiliser ou pas une sauvegarde statique pour limiter les
accès SQL quand on est dans un traitement qui le nécessite.
Il est possible de choisir les champs à récupérer et un pipeline
post_relecture permet de compléter la description brute.

C'est donc une fonction très générique (peut-être trop mais finalement si
ça marche pourquoi pas) et qui pourrait remplacer pas mal d'appels SQL
récurrents qui à la longue nuisent un peu à la lisibilité du code ou à la
maintenance (enfin c'est mon avis).
Je vous mets le code ci-dessous. Pensez-vous qu'on aurait intérêt à ajouter
cette fonction à l'API objet ?
Si oui, on pourrait se poser la question pour les fonctions objet_supprimer
et objet_repertorier.

function objet_lire($objet, $champ_id, $valeur_id, $informations =
array(), $stockage = false) {

   // Initialisation du tableau des descriptions et des id d'objet (au
sens id_xxx).
   // Le tableau des descriptions est toujours indexé par l'objet et l'id objet.
   static $descriptions = array();
   static $ids = array();

   // On détermine le nom du champ id de la table.
   include_spip('base/objets');
   $table_id = id_table_objet($objet);

   // On détermine si on a passé l'id objet ou un autre identifiant
unique de la table :
   if ($champ_id != $table_id) {
      // on a passé un identifiant différent que l'id de l'objet, on
cherche si cet objet a déjà été rencontré
      // car dans ce cas on a déjà stocké son id objet.
      $index = isset($ids[$valeur_id]) ? $ids[$valeur_id] : 0;
   } else {
      $index = $valeur_id;
   }

   // Même si on a pas demandé le stockage sur l'appel en cours, on
vérifie si l'objet demandé
   // n'est pas déjà stocké.
   if (isset($descriptions[$objet][$index])) {
      $description = $descriptions[$objet][$index];
   } else {
      $description = array();
   }

   // Si l'objet n'a pas encore été stocké, il faut le récupérer sa
description complète.
   if (!$description) {
      // On récupère la table SQL à partir du type d'objet.
      $table = table_objet_sql($objet);

      // La condition est appliquée sur le champ désigné par
l'utilisateur. Si ce champ n'est pas l'id objet
      // on considère qu'il est de type chaine.
      $where = ($champ_id != $table_id)
         ? array("${champ_id}=" . sql_quote($valeur_id))
         : array("${champ_id}=" . intval($valeur_id));

      // Acquisition de tous les champs de l'objet : si l'accès SQL
retourne une erreur on renvoie un tableau vide.
      if (!$description = sql_fetsel('*', $table, $where)) {
         $description = array();
      } else {
         // On complète éventuellement la description brute de l'objet
via le pipeline post_lecture.
         $description = pipeline('post_lecture', $description);
      }

      // Si on a demandé le stockage statique on sauvegarde la
description à l'index correspondant à l'id objet.
      if ($stockage) {
         if (!$index) {
            // Première sauvegarde de l'objet qui est forcément lu via
un champ qui n'est pas l'id objet.
            // Il faut donc stocker l'index pour un futur appel si la
description est non vide.
            if ($description) {
               $index = $description[$table_id];
               $ids[$valeur_id] = $index;
            }
         }

         // Si l'index a bien été trouvé, on stocke la description à cet index.
         if ($index) {
            $descriptions[$objet][$index] = $description;
         }
      }
   }

   // On ne retourne maintenant que les champs demandés.
   if ($description and $informations) {
      // Extraction des seules informations demandées.
      // -- si on demande une information unique on renvoie la valeur
simple, sinon on renvoie un tableau.
      // -- si une information n'est pas un champ valide elle n'est
pas renvoyée sans renvoyer d'erreur.
      if (is_array($informations)) {
         if (count($informations) == 1) {
            // Tableau d'une seule information : on revient à une chaine unique.
            $informations = array_shift($informations);
         } else {
            // Tableau des informations valides
            $description = array_intersect_key($description,
array_flip($informations));
         }
      }

      if (is_string($informations)) {
         // Valeur unique demandée.
         $description = isset($description[$informations]) ?
$description[$informations] : '';
      }
   }

   return $description;
}


A vous lire.

++
Eric
_______________________________________________
liste: https://listes.rezo.net/mailman/listinfo/spip-dev
doc: http://www.spip.net/
dev: http://trac.rezo.net/trac/spip/
irc://irc.freenode.net/spip

Répondre à