[PLUGINS] +les plugins de bases
[ptitvelo/web/www.git] / www / plugins / saisies / inc / saisies_afficher.php
diff --git a/www/plugins/saisies/inc/saisies_afficher.php b/www/plugins/saisies/inc/saisies_afficher.php
new file mode 100644 (file)
index 0000000..eb02b78
--- /dev/null
@@ -0,0 +1,421 @@
+<?php\r
+\r
+/**\r
+ * Gestion de l'affichage des saisies\r
+ *\r
+ * @return SPIP\Saisies\Afficher\r
+**/\r
+\r
+// Sécurité\r
+if (!defined('_ECRIRE_INC_VERSION')) return;\r
+\r
+/**\r
+ * Indique si une saisie peut être affichée.\r
+ * \r
+ * On s'appuie sur l'éventuelle clé "editable" du $champ.\r
+ * Si editable vaut :\r
+ *    - absent : le champ est éditable\r
+ *    - 1, le champ est éditable\r
+ *    - 0, le champ n'est pas éditable\r
+ *    - -1, le champ est éditable s'il y a du contenu dans le champ (l'environnement)\r
+ *         ou dans un de ses enfants (fieldsets)\r
+ *\r
+ * @param array $champ\r
+ *     Tableau de description de la saisie\r
+ * @param array $env\r
+ *     Environnement transmis à la saisie, certainement l'environnement du formulaire\r
+ * @param bool $utiliser_editable\r
+ *     - false pour juste tester le cas -1\r
+ * \r
+ * @return bool\r
+ *     Retourne un booléen indiquant l'état éditable ou pas :\r
+ *     - true si la saisie est éditable (peut être affichée)\r
+ *     - false sinon\r
+ */\r
+function saisie_editable($champ, $env, $utiliser_editable=true) {\r
+       if ($utiliser_editable) {\r
+               // si le champ n'est pas éditable, on sort.\r
+               if (!isset($champ['editable'])) {\r
+                       return true;\r
+               }\r
+               $editable = $champ['editable'];\r
+\r
+               if ($editable > 0) {\r
+                       return true;\r
+               }\r
+               if ($editable == 0) {\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       // cas -1\r
+       // name de la saisie\r
+       if (isset($champ['options']['nom'])) {\r
+               // si on a le name dans l'environnement, on le teste\r
+               $nom = $champ['options']['nom'];\r
+               if (isset($env[$nom])) {\r
+                       return $env[$nom] ? true : false ;\r
+               }\r
+       }\r
+       // sinon, si on a des sous saisies\r
+       if (isset($champ['saisies']) and is_array($champ['saisies'])) {\r
+               foreach($champ['saisies'] as $saisie) {\r
+                       if (saisie_editable($saisie, $env, false)) {\r
+                               return true;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       // aucun des paramètres demandés n'avait de contenu\r
+       return false;\r
+}\r
+\r
+/**\r
+ * Génère une saisie à partir d'un tableau la décrivant et de l'environnement\r
+ *\r
+ * @param array $champ\r
+ *     Description de la saisie.\r
+ *     Le tableau doit être de la forme suivante :\r
+ *     array(\r
+ *                     'saisie' => 'input',\r
+ *                     'options' => array(\r
+ *                             'nom' => 'le_name',\r
+ *                             'label' => 'Un titre plus joli',\r
+ *                             'obligatoire' => 'oui',\r
+ *                             'explication' => 'Remplissez ce champ en utilisant votre clavier.'\r
+ *                     )\r
+ *     )\r
+ * @param array $env\r
+ *     Environnement du formulaire\r
+ *     Permet de savoir les valeurs actuelles des contenus des saisies,\r
+ *     les erreurs eventuelles présentes...\r
+ * @return string\r
+ *     Code HTML des saisies de formulaire\r
+ */\r
+function saisies_generer_html($champ, $env=array()){\r
+       // Si le parametre n'est pas bon, on genere du vide\r
+       if (!is_array($champ))\r
+               return '';\r
+\r
+       // Si la saisie n'est pas editable, on sort aussi.\r
+       if (!saisie_editable($champ, $env)) {\r
+               return '';\r
+       }\r
+       \r
+       $contexte = array();\r
+       \r
+       // On sélectionne le type de saisie\r
+       $contexte['type_saisie'] = $champ['saisie'];\r
+       // Identifiant unique de saisie, si present\r
+       if (isset($champ['identifiant'])) {\r
+               $contexte['id_saisie'] = $champ['identifiant'];\r
+       }\r
+\r
+       // Peut-être des transformations à faire sur les options textuelles\r
+       $options = $champ['options'];\r
+       foreach ($options as $option => $valeur){\r
+               if ($option == 'datas') {\r
+                       // exploser une chaine datas en tableau (applique _T_ou_typo sur chaque valeur)\r
+                       $options[$option] = saisies_chaine2tableau($valeur);\r
+               } else {\r
+                       $options[$option] = _T_ou_typo($valeur, 'multi');\r
+               }\r
+       }\r
+       \r
+       // On ajoute les options propres à la saisie\r
+       $contexte = array_merge($contexte, $options);\r
+\r
+       // Si env est définie dans les options ou qu'il y a des enfants, on ajoute tout l'environnement\r
+       if (isset($contexte['env']) or (isset($champ['saisies']) AND is_array($champ['saisies']))) {\r
+               unset($contexte['env']);\r
+\r
+               // on sauve l'ancien environnement\r
+               // car les sous-saisies ne doivent pas être affectees\r
+               // par les modification sur l'environnement servant à generer la saisie mère\r
+               $contexte['_env'] = $env;\r
+               \r
+               // À partir du moment où on passe tout l'environnement, il faut enlever certains éléments qui ne doivent absolument provenir que des options\r
+               unset($env['inserer_debut']);\r
+               unset($env['inserer_fin']);\r
+               $saisies_disponibles = saisies_lister_disponibles();\r
+               if (isset($saisies_disponibles[$contexte['type_saisie']]) and is_array($saisies_disponibles[$contexte['type_saisie']]['options'])) {\r
+                       $options_a_supprimer = saisies_lister_champs($saisies_disponibles[$contexte['type_saisie']]['options']);\r
+                       foreach ($options_a_supprimer as $option_a_supprimer){\r
+                               unset($env[$option_a_supprimer]);\r
+                       }\r
+               }\r
+               \r
+               $contexte = array_merge($env, $contexte);\r
+       }\r
+       // Sinon on ne sélectionne que quelques éléments importants\r
+       else{\r
+               // On récupère la liste des erreurs\r
+               $contexte['erreurs'] = $env['erreurs'];\r
+               // On ajoute toujours le bon self\r
+               $contexte['self'] = self();\r
+       }\r
+\r
+       // Dans tous les cas on récupère de l'environnement la valeur actuelle du champ\r
+       // Si le nom du champ est un tableau indexé, il faut parser !\r
+       if (preg_match('/([\w]+)((\[[\w]+\])+)/', $contexte['nom'], $separe)){\r
+               $contexte['valeur'] = $env[$separe[1]];\r
+               preg_match_all('/\[([\w]+)\]/', $separe[2], $index);\r
+               // On va chercher au fond du tableau\r
+               foreach($index[1] as $cle){\r
+                       $contexte['valeur'] = isset($contexte['valeur'][$cle]) ? $contexte['valeur'][$cle] : null;\r
+               }\r
+       }\r
+       // Sinon la valeur est juste celle du nom\r
+       else {\r
+               $contexte['valeur'] = (isset($env[$contexte['nom']]) ? $env[$contexte['nom']] : null);\r
+       }\r
+\r
+       // Si ya des enfants on les remonte dans le contexte\r
+       if (isset($champ['saisies']) and is_array($champ['saisies']))\r
+               $contexte['saisies'] = $champ['saisies'];\r
+       \r
+       // On génère la saisie\r
+       return recuperer_fond(\r
+               'saisies/_base',\r
+               $contexte\r
+       );\r
+}\r
+\r
+/**\r
+ * Génère une vue d'une saisie à partir d'un tableau la décrivant\r
+ *\r
+ * @see saisies_generer_html()\r
+ * @param array $saisie\r
+ *     Tableau de description d'une saisie\r
+ * @param array $env\r
+ *     L'environnement, contenant normalement la réponse à la saisie\r
+ * @param array $env_obligatoire\r
+ *     ???\r
+ * @return string\r
+ *     Code HTML de la vue de la saisie\r
+ */\r
+function saisies_generer_vue($saisie, $env=array(), $env_obligatoire=array()){\r
+       // Si le paramètre n'est pas bon, on génère du vide\r
+       if (!is_array($saisie))\r
+               return '';\r
+\r
+       $contexte = array();\r
+               \r
+       // On sélectionne le type de saisie\r
+       $contexte['type_saisie'] = $saisie['saisie'];\r
+       \r
+       // Peut-être des transformations à faire sur les options textuelles\r
+       $options = $saisie['options'];\r
+       foreach ($options as $option => $valeur){\r
+               if ($option == 'datas') {\r
+                       // exploser une chaine datas en tableau (applique _T_ou_typo sur chaque valeur)\r
+                       $options[$option] = saisies_chaine2tableau($valeur);\r
+               } else {\r
+                       $options[$option] = _T_ou_typo($valeur, 'multi');\r
+               }\r
+       }\r
+       \r
+       // On ajoute les options propres à la saisie\r
+       $contexte = array_merge($contexte, $options);\r
+\r
+       // Si env est définie dans les options ou qu'il y a des enfants, on ajoute tout l'environnement\r
+       if (isset($contexte['env']) or (isset($saisie['saisies']) AND is_array($saisie['saisies']))){\r
+               unset($contexte['env']);\r
+\r
+               // on sauve l'ancien environnement\r
+               // car les sous-saisies ne doivent pas être affectees\r
+               // par les modification sur l'environnement servant à generer la saisie mère\r
+               $contexte['_env'] = $env;\r
+\r
+               // À partir du moment où on passe tout l'environnement, il faut enlever \r
+               // certains éléments qui ne doivent absolument provenir que des options\r
+               $saisies_disponibles = saisies_lister_disponibles();\r
+               if (is_array($saisies_disponibles[$contexte['type_saisie']]['options'])){\r
+                       $options_a_supprimer = saisies_lister_champs($saisies_disponibles[$contexte['type_saisie']]['options']);\r
+                       foreach ($options_a_supprimer as $option_a_supprimer){\r
+                               unset($env[$option_a_supprimer]);\r
+                       }\r
+               }\r
+               \r
+               $contexte = array_merge($env, $contexte);\r
+       }\r
+\r
+       // Dans tous les cas on récupère de l'environnement la valeur actuelle du champ\r
+       \r
+       // On regarde en priorité s'il y a un tableau listant toutes les valeurs\r
+       if ($env['valeurs'] and is_array($env['valeurs']) and isset($env['valeurs'][$contexte['nom']])){\r
+               $contexte['valeur'] = $env['valeurs'][$contexte['nom']];\r
+       }\r
+       // Si le nom du champ est un tableau indexé, il faut parser !\r
+       elseif (preg_match('/([\w]+)((\[[\w]+\])+)/', $contexte['nom'], $separe)){\r
+               $contexte['valeur'] = $env[$separe[1]];\r
+               preg_match_all('/\[([\w]+)\]/', $separe[2], $index);\r
+               // On va chercher au fond du tableau\r
+               foreach($index[1] as $cle){\r
+                       $contexte['valeur'] = $contexte['valeur'][$cle];\r
+               }\r
+       }\r
+       // Sinon la valeur est juste celle du nom\r
+       else {\r
+               // certains n'ont pas de nom (fieldset)\r
+               $contexte['valeur'] = isset($env[$contexte['nom']]) ? $env[$contexte['nom']] : '';\r
+       }\r
+\r
+       // Si ya des enfants on les remonte dans le contexte\r
+       if (isset($saisie['saisies']) AND is_array($saisie['saisies']))\r
+               $contexte['saisies'] = $saisie['saisies'];\r
+\r
+       if (is_array($env_obligatoire)) {\r
+               $contexte = array_merge($contexte, $env_obligatoire);\r
+       }\r
+\r
+       // On génère la saisie\r
+       return recuperer_fond(\r
+               'saisies-vues/_base',\r
+               $contexte\r
+       );\r
+}\r
+\r
+/**\r
+ * Génère, à partir d'un tableau de saisie le code javascript ajouté à la fin de #GENERER_SAISIES\r
+ * pour produire un affichage conditionnel des saisies ayant une option afficher_si.\r
+ *\r
+ * @param array $saisies\r
+ *     Tableau de descriptions des saisies\r
+ * @param string $id_form\r
+ *     Identifiant unique pour le formulaire\r
+ * @return text\r
+ *     Code javascript\r
+ */\r
+function saisies_generer_js_afficher_si($saisies,$id_form){\r
+       $i = 0;\r
+       $saisies = saisies_lister_par_nom($saisies,true);\r
+       $code = '';\r
+       $code .= '(function($){';\r
+       $code .= '$(document).ready(function(){';\r
+               $code .= 'verifier_saisies_'.$id_form.' = function(form){';\r
+                               foreach ($saisies as $saisie) {\r
+                                       // on utilise comme selecteur l'identifiant de saisie en priorite s'il est connu\r
+                                       // parce que li_class = 'tableau[nom][option]' ne fonctionne evidement pas\r
+                                       // lorsque le name est un tableau\r
+                                       if (isset($saisie['options']['afficher_si'])) {\r
+                                               $i++;\r
+                                               // retrouver la classe css probable\r
+                                               switch ($saisie['saisie']) {\r
+                                                       case 'fieldset':\r
+                                                               $class_li = 'fieldset_'.$saisie['options']['nom'];\r
+                                                               break;\r
+                                                       case 'explication':\r
+                                                               $class_li = 'explication_'.$saisie['options']['nom'];\r
+                                                               break;\r
+                                                       default:\r
+                                                               $class_li = 'editer_'.$saisie['options']['nom'];\r
+                                               }\r
+                                               $condition = $saisie['options']['afficher_si'];\r
+                                               // retrouver l'identifiant\r
+                                               $identifiant = '';\r
+                                               if (isset($saisie['identifiant']) and $saisie['identifiant']) {\r
+                                                       $identifiant = $saisie['identifiant'];\r
+                                               }\r
+                                               // On gère le cas @plugin:non_plugin@\r
+                                               preg_match_all('#@plugin:(.+)@#U', $condition, $matches);\r
+                                               foreach ($matches[1] as $plug) {\r
+                                                       if (defined('_DIR_PLUGIN_'.strtoupper($plug)))\r
+                                                               $condition = preg_replace('#@plugin:'.$plug.'@#U', 'true', $condition);\r
+                                                       else\r
+                                                               $condition = preg_replace('#@plugin:'.$plug.'@#U', 'false', $condition);\r
+                                               }\r
+                                               // On gère le cas @config:plugin:meta@ suivi d'un test\r
+                                               preg_match_all('#@config:(.+):(.+)@#U', $condition, $matches);\r
+                                               foreach ($matches[1] as $plugin) {\r
+                                                       $config = lire_config($plugin);\r
+                                                       $condition = preg_replace('#@config:'.$plugin.':'.$matches[2][0].'@#U', '"'.$config[$matches[2][0]].'"', $condition);\r
+                                               }\r
+                                               // On transforme en une condition valide\r
+                                               preg_match_all('#@(.+)@#U', $condition, $matches);\r
+                                               foreach ($matches[1] as $nom) {\r
+                                                       switch($saisies[$nom]['saisie']) {\r
+                                                               case 'radio':\r
+                                                               case 'oui_non':\r
+                                                                       $condition = preg_replace('#@'.preg_quote($nom).'@#U', '$(form).find("[name=\''.$nom.'\']:checked").val()', $condition);\r
+                                                                       break;\r
+                                                               case 'case':\r
+                                                                       $condition = preg_replace('#@'.preg_quote($nom).'@#U', '($(form).find("[name=\''.$nom.'\']").is(":checked") ? $(form).find("[name=\''.$nom.'\']").val() : "")', $condition);\r
+                                                                       break;\r
+                                                               default:\r
+                                                                       $condition = preg_replace('#@'.preg_quote($nom).'@#U', '$(form).find("[name=\''.$nom.'\']").val()', $condition);\r
+                                                       }\r
+                                               }\r
+                                               if ($identifiant) {\r
+                                                       $sel = "li[data-id='$identifiant']";\r
+                                               } else {\r
+                                                       $sel = "li.$class_li";\r
+                                               }\r
+                                               $code .= 'if ('.$condition.') {$(form).find("'.$sel.'").show(400);} ';\r
+                                               $code .= 'else {$(form).find("'.$sel.'").hide(400).css("display", "none");} ';\r
+                                       }\r
+                               }\r
+               $code .= '};';\r
+               $code .= '$("li#afficher_si_'.$id_form.'").parents("form").each(function(){verifier_saisies_'.$id_form.'(this);});';\r
+               $code .= '$("li#afficher_si_'.$id_form.'").parents("form").change(function(){verifier_saisies_'.$id_form.'(this);});';\r
+       $code .= '});';\r
+       $code .= '})(jQuery);';\r
+       return $i>0 ? $code : '';\r
+}\r
+\r
+/**\r
+ * Lorsque l'on affiche les saisies (#VOIR_SAISIES), les saisies ayant une option afficher_si\r
+ * et dont les conditions ne sont pas remplies doivent être retirées du tableau de saisies.\r
+ * \r
+ * Cette fonction sert aussi lors de la vérification des saisies avec saisies_verifier().\r
+ * À ce moment là, les saisies non affichées sont retirées de _request\r
+ * (on passe leur valeur à NULL).\r
+ *\r
+ * @param array $saisies\r
+ *     Tableau de descriptions de saisies\r
+ * @param array|null $env\r
+ *     Tableau d'environnement transmis dans inclure/voi_saisies.html,\r
+ *     NULL si on doit rechercher dans _request (pour saisies_verifier()).\r
+ * @return array\r
+ *     Tableau de descriptions de saisies\r
+ */\r
+function saisies_verifier_afficher_si($saisies, $env=NULL) {\r
+       // eviter une erreur par maladresse d'appel :)\r
+       if (!is_array($saisies)) {\r
+               return array();\r
+       }\r
+       foreach ($saisies as $cle => $saisie) {\r
+               if (isset($saisie['options']['afficher_si'])) {\r
+                       $condition = $saisie['options']['afficher_si'];\r
+                       // On gère le cas @plugin:non_plugin@\r
+                       preg_match_all('#@plugin:(.+)@#U', $condition, $matches);\r
+                       foreach ($matches[1] as $plug) {\r
+                               if (defined('_DIR_PLUGIN_'.strtoupper($plug)))\r
+                                       $condition = preg_replace('#@plugin:'.$plug.'@#U', 'true', $condition);\r
+                               else\r
+                                       $condition = preg_replace('#@plugin:'.$plug.'@#U', 'false', $condition);\r
+                       }\r
+                       // On gère le cas @config:plugin:meta@ suivi d'un test\r
+                       preg_match_all('#@config:(.+):(.+)@#U', $condition, $matches);\r
+                       foreach ($matches[1] as $plugin) {\r
+                               $config = lire_config($plugin);\r
+                               $condition = preg_replace('#@config:'.$plugin.':'.$matches[2][0].'@#U', '"'.$config[$matches[2][0]].'"', $condition);\r
+                       }\r
+                       // On transforme en une condition valide\r
+                       if (is_null($env))\r
+                               $condition = preg_replace('#@(.+)@#U', '_request(\'$1\')', $condition);\r
+                       else\r
+                               $condition = preg_replace('#@(.+)@#U', '$env["valeurs"][\'$1\']', $condition);\r
+                       eval('$ok = '.$condition.';');\r
+                       if (!$ok) {\r
+                               unset($saisies[$cle]);\r
+                               if (is_null($env)) set_request($saisie['options']['nom'],NULL);\r
+                       }\r
+               }\r
+               if (isset($saisies[$cle]['saisies'])) // S'il s'agit d'un fieldset ou equivalent, verifier les sous-saisies\r
+                       $saisies[$cle]['saisies'] = saisies_verifier_afficher_si($saisies[$cle]['saisies'], $env);\r
+       }\r
+       return $saisies;\r
+}\r
+\r
+?>\r