[PLUGINS] +crayons
[lhc/web/clavette_www.git] / www / plugins / crayons / inc / crayons.php
diff --git a/www/plugins/crayons/inc/crayons.php b/www/plugins/crayons/inc/crayons.php
new file mode 100644 (file)
index 0000000..2039c27
--- /dev/null
@@ -0,0 +1,701 @@
+<?php\r
+/**\r
+ * Crayons \r
+ * plugin for spip \r
+ * (c) Fil, toggg 2006-2013\r
+ * licence GPL\r
+ */\r
+\r
+if (!defined("_ECRIRE_INC_VERSION")) return;\r
+\r
+define('_PREG_CRAYON', ',crayon\b[^<>\'"]+?\b((\w+)-(\w+)-(\w+(?:-\w+)*))\b,');\r
+\r
+// Compatibilite pour 1.92 : on a besoin de sql_fetch et table_objet_sql\r
+if ($GLOBALS['spip_version_code'] < '1.93' AND $f = charger_fonction('compat_crayons', 'inc'))\r
+       $f();\r
+\r
+// Autoriser les crayons sur les tables non SPIP ?\r
+// Par defaut : oui (pour les admins complets, si autoriser_defaut_dist()) ;\r
+// mettre a false en cas de mutualisation par prefixe de table,\r
+// sinon on ne peut pas garantir que les sites sont hermetiques\r
+if(!defined('_CRAYONS_TABLES_EXTERNES'))\r
+       define('_CRAYONS_TABLES_EXTERNES', true);\r
+\r
+// Autorisations non prevues par le core\r
+include_spip('inc/autoriser');\r
+\r
+include_spip('inc/crayons-json');\r
+\r
+if (!function_exists('autoriser_meta_modifier_dist')) {\r
+/**\r
+ * Autorisation d'éditer les configurations dans spip_meta\r
+ *\r
+ * Les admins complets OK pour certains champs,\r
+ * Sinon, il faut être webmestre\r
+ *\r
+ * @note\r
+ *  Attention sur les SPIP < 11515 (avant 04/2008) inc/autoriser\r
+ *  passe seulement intval($id) alors qu'ici la cle est une chaine...\r
+ *\r
+ * @param  string $faire Action demandée\r
+ * @param  string $type  Type d'objet sur lequel appliquer l'action\r
+ * @param  int    $id    Identifiant de l'objet\r
+ * @param  array  $qui   Description de l'auteur demandant l'autorisation\r
+ * @param  array  $opt   Options de cette autorisation\r
+ * @return bool          true s'il a le droit, false sinon\r
+**/\r
+function autoriser_meta_modifier_dist($faire, $type, $id, $qui, $opt) {\r
+       // Certaines cles de configuration sont echapées ici (cf #EDIT_CONFIG{demo/truc})\r
+       // $id = str_replace('__', '/', $id);\r
+       if (in_array("$id", array(\r
+               'nom_site', 'slogan_site', 'descriptif_site', 'email_webmaster'\r
+       )))\r
+               return autoriser('configurer', null, null, $qui);\r
+       else\r
+               return autoriser('webmestre', null, null, $qui);\r
+}\r
+}\r
+\r
+// table spip_messages, la c'est tout simplement non (peut mieux faire,\r
+// mais c'est a voir dans le core/organiseur ou dans autorite)\r
+if (defined('_DIR_PLUGIN_ORGANISEUR'))\r
+       include_spip('organiseur_autoriser');\r
+if (!function_exists('autoriser_message_modifier_dist')) {\r
+       function autoriser_message_modifier_dist($faire, $type, $id, $qui, $opt) {\r
+               return false;\r
+       }\r
+}\r
+//compat 192 documents\r
+if ($GLOBALS['spip_version_code'] < '1.93'){\r
+       if (!function_exists('get_spip_doc')){\r
+               function get_spip_doc($fichier) {\r
+                       // fichier distant\r
+                       if (preg_match(',^\w+://,', $fichier))\r
+                                       return $fichier;\r
+\r
+                       // gestion d'erreurs, fichier=''\r
+                       if (!strlen($fichier))\r
+                                       return false;\r
+\r
+                       // fichier normal\r
+                       return (strpos($fichier, _DIR_IMG) === false)\r
+                       ? _DIR_IMG . $fichier\r
+                       : $fichier;\r
+               }\r
+       }\r
+}\r
+\r
+// Autoriser l'usage des crayons ?\r
+function autoriser_crayonner_dist($faire, $type, $id, $qui, $opt) {\r
+       // Le type pouvant etre une table, verifier les autoriser('modifier')\r
+       // correspondant ; ils demandent le nom de l'objet: spip_articles => article\r
+       // ex: spip_articles => 'article'\r
+       $type = preg_replace(',^spip_(.*?)s?$,', '\1', $type);\r
+       if (strlen($GLOBALS['table_prefix']))\r
+               $type = preg_replace(',^'.$GLOBALS['table_prefix'].'_(.*?)s?$,', '\1', $type);\r
+\r
+       // Tables non SPIP ? Si elles sont interdites il faut regarder\r
+       // quelle table on appelle, et verifier si elle est "interne"\r
+       if (!_CRAYONS_TABLES_EXTERNES) {\r
+               include_spip('base/serial');\r
+               include_spip('base/auxiliaires');\r
+               include_spip('public/parametrer');\r
+               if (!isset($GLOBALS['tables_principales']['spip_'.table_objet($type)])\r
+               AND !isset($GLOBALS['tables_auxiliaires']['spip_'.table_objet($type)]))\r
+                       return false;\r
+       }\r
+\r
+       // Traduire le modele en liste de champs\r
+       if (isset($opt['modele']))\r
+               $opt['champ'] = $opt['modele'];\r
+\r
+       // Pour un auteur, si le champ est statut ou email, signaler l'option\r
+       // ad hoc (cf. inc/autoriser)\r
+       if ($type == 'auteur'\r
+       AND in_array($opt['champ'], array('statut', 'email')))\r
+               $opt[$opt['champ']] = true;\r
+\r
+       return (\r
+                autoriser('modifier', $type, $id, $qui, $opt)\r
+       );\r
+}\r
+\r
+// Si un logo est demande, on renvoie la date dudit logo (permettra de gerer\r
+// un "modifie par ailleurs" si la date a change, rien de plus)\r
+function valeur_champ_logo($table, $id, $champ) {\r
+       $chercher_logo = charger_fonction('chercher_logo', 'inc');\r
+       $on = $chercher_logo($id, id_table_objet($table), 'on');\r
+       return $on ? filemtime($on[0]) : false;\r
+}\r
+\r
+// Idem : si un doc est demande, on renvoie la date du doc\r
+function valeur_champ_document($table, $id, $champ) {\r
+       $s = spip_query("SELECT date FROM spip_documents WHERE id_document="._q($id));\r
+       if ($t = sql_fetch($s))\r
+               return $t['date'];\r
+}\r
+\r
+function valeur_champ_vignette($table, $id, $champ) {\r
+       $vignette = sql_getfetsel('id_vignette','spip_documents','id_document='.intval($id));\r
+       if(is_numeric($vignette) && ($vignette > 0)){\r
+               $date = sql_getfetsel('date','spip_documents','id_document='.intval($vignette));\r
+       }\r
+       return $date ? $date : false;\r
+}\r
+// cette fonction de revision recoit le fichier upload a passer en logo\r
+// en reference : le nom du widget, pour aller chercher d'autres donnees\r
+// (ex: supprimer)\r
+function logo_revision($id, $file, $type, $ref) {\r
+       $chercher_logo = charger_fonction('chercher_logo', 'inc');\r
+       $_id_objet = id_table_objet($type);\r
+\r
+       // Chargement d'un nouveau logo ?\r
+       if ($file['logo']) {\r
+               define('FILE_UPLOAD', true); // message pour crayons_json_export :(\r
+\r
+               if (include_spip("action/editer_logo")\r
+                 AND function_exists("logo_modifier")){\r
+                       logo_modifier($type, $id, "on", $file['logo']);\r
+               }\r
+               // compat SPIP < 3.1\r
+               else {\r
+                       // supprimer l'ancien logo\r
+                       $on = $chercher_logo($id, $_id_objet, 'on');\r
+                       if ($on) @unlink($on[0]);\r
+\r
+                       // ajouter le nouveau\r
+                       include_spip('action/iconifier');\r
+                       action_spip_image_ajouter_dist(\r
+                               type_du_logo($_id_objet).'on'.$id, false, false\r
+                       ); // beurk\r
+               }\r
+       }\r
+\r
+       else {\r
+               // Suppression du logo ?\r
+               if ($wid = array_pop($ref)\r
+               AND $_POST['content_'.$wid.'_logo_supprimer'] == 'on') {\r
+                       if (include_spip("action/editer_logo")\r
+                         AND function_exists("logo_supprimer")){\r
+                               logo_supprimer($type, $id, "on");\r
+                       }\r
+                       else {\r
+                               if ($on = $chercher_logo($id, $_id_objet, 'on'))\r
+                                       @unlink($on[0]);\r
+                       }\r
+               }\r
+       }\r
+\r
+       // Reduire le logo ?\r
+       if (is_array($cfg = @unserialize($GLOBALS['meta']['crayons']))\r
+       AND $max = intval($cfg['reduire_logo'])) {\r
+               $on = $chercher_logo($id, $_id_objet, 'on');\r
+               include_spip('inc/filtres');\r
+               @copy($on[0], $temp = _DIR_VAR.'tmp'.rand(0,999).'.'.$on[3]);\r
+               $img1 = filtrer('image_reduire', $temp, $max);\r
+               $img2 = preg_replace(',[?].*,', '', extraire_attribut($img1, 'src'));\r
+               if (@file_exists($img2)\r
+               AND $img2 !=  $temp) {\r
+                       if (include_spip("action/editer_logo")\r
+                         AND function_exists("logo_modifier")){\r
+                               logo_modifier($type, $id, "on", $img2);\r
+                       }\r
+                       else {\r
+                               @unlink($on[0]);\r
+                               $dest = $on[1].$on[2].'.'\r
+                                       .preg_replace(',^.*\.(gif|jpg|png)$,', '\1', $img2);\r
+                               @rename($img2,$dest);\r
+                       }\r
+               }\r
+               @unlink($temp);\r
+       }\r
+\r
+       return true;\r
+}\r
+\r
+\r
+// cette fonction de revision recoit le fichier upload a passer en document\r
+function document_fichier_revision($id, $data, $type, $ref) {\r
+\r
+       $s = spip_query("SELECT * FROM spip_documents WHERE id_document=".intval($id));\r
+       if (!$t = sql_fetch($s))\r
+               return false;\r
+\r
+       /*\r
+       // Envoi d'une URL de document distant ?\r
+       // TODO: verifier l'extension distante, sinon tout explose\r
+       if ($data['fichier']\r
+       AND preg_match(',^(https?|ftp)://.+,', $data['fichier'])) {\r
+               include_spip('inc/modifier');\r
+               modifier_contenu('document', $id,\r
+                       array('champs' => array('fichier', 'distant')),\r
+                       array('fichier' => $data['fichier'], 'distant' => 'oui')\r
+               );\r
+               return true;\r
+       }\r
+       else\r
+       */\r
+\r
+       // Chargement d'un nouveau doc ?\r
+       if ($data['document']) {\r
+\r
+               $arg = $data['document'];\r
+               \r
+               /** \r
+                * Méthode >= SPIP 3.0 \r
+                * ou SPIP 2.x + Mediathèque\r
+                */ \r
+               if($ajouter_documents = charger_fonction('ajouter_documents','action',true)){ \r
+                       $actifs = $ajouter_documents($id,array($arg),'', 0,$t['mode']);\r
+                       $x = reset($actifs);\r
+                       if(is_numeric($x))\r
+                               return true;\r
+                       else\r
+                               return false;\r
+               }\r
+               /**\r
+                * Méthode SPIP < 3.0\r
+                */\r
+               else if($ajouter_documents = charger_fonction('ajouter_documents','inc',true)){ \r
+                       check_upload_error($arg['error']);\r
+                       $x = $ajouter_documents($arg['tmp_name'], $arg['name'],\r
+                                       'article', 0, 'document', null, $actifs);\r
+                       // $actifs contient l'id_document nouvellement cree\r
+                       // on recopie les donnees interessantes dans l'ancien\r
+                       $extension=", extension ";\r
+                       //compat 192\r
+                       if ($GLOBALS['spip_version_code'] < '1.93')\r
+                               $extension="";\r
+\r
+                       if ($id_new = array_pop($actifs)\r
+                       AND $s = spip_query("SELECT fichier, taille, largeur, hauteur $extension, distant FROM spip_documents\r
+                               WHERE id_document="._q($id_new))\r
+                       AND $new = sql_fetch($s)) {\r
+                               define('FILE_UPLOAD', true); // message pour crayons_json_export :(\r
+\r
+                               // Une vignette doit rester une image\r
+                               if ($t['mode'] == 'vignette'\r
+                               AND !in_array($new['extension'], array('jpg', 'gif', 'png')))\r
+                                       return false;\r
+\r
+                               // Maintenant on est bon, on recopie les nouvelles donnees\r
+                               // dans l'ancienne ligne spip_documents\r
+                               include_spip('inc/modifier');\r
+                               modifier_contenu('document', $id,\r
+                                       # 'champs' inutile a partir de SPIP 11348\r
+                                       array('champs' => array_keys($new)),\r
+                                       $new);\r
+\r
+                               // supprimer l'ancien document (sauf s'il etait distant)\r
+                               if ($t['distant'] != 'oui'\r
+                               AND file_exists(get_spip_doc($t['fichier'])))\r
+                                       supprimer_fichier(get_spip_doc($t['fichier']));\r
+\r
+                               // Effacer la ligne temporaire de spip_document\r
+                               spip_query("DELETE FROM spip_documents WHERE id_document="._q($id_new));\r
+\r
+                               // oublier id_document temporaire (ca marche chez moi, sinon bof)\r
+                               spip_query("ALTER TABLE spip_documents AUTO_INCREMENT="._q($id_new));\r
+\r
+                               return true;\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+// cette fonction de revision soit supprime la vignette d'un document,\r
+// soit recoit le fichier upload a passer ou remplacer la vignette du document\r
+function vignette_revision($id, $data, $type, $ref) {\r
+       $s = sql_fetsel("id_document,id_vignette","spip_documents","id_document=".intval($id));\r
+       if (!is_array($s))\r
+               return false;\r
+\r
+       include_spip('inc/modifier');\r
+       include_spip('inc/documents');\r
+       include_spip('action/editer_document');//pour revision_document\r
+       // Chargement d'un nouveau doc ?\r
+       if ($data['vignette']) {\r
+               define('FILE_UPLOAD', true);\r
+               if(is_numeric($s['id_vignette']) && ($s['id_vignette']>0)){\r
+                       spip_log('suppression de la vignette');\r
+                       // Suppression du document\r
+                       $vignette = sql_getfetsel('fichier', 'spip_documents', 'id_document='.intval($s['id_vignette']));\r
+                       if (@file_exists($f = get_spip_doc($vignette))) { \r
+                               spip_log("efface $f"); \r
+                               supprimer_fichier($f); \r
+                       }\r
+                       sql_delete('spip_documents', 'id_document='.intval($s['id_vignette']));\r
+                       sql_delete('spip_documents_liens', 'id_document='.intval($s['id_vignette']));\r
+\r
+                       pipeline('post_edition',\r
+                               array(\r
+                                       'args' => array(\r
+                                               'operation' => 'supprimer_document',\r
+                                               'table' => 'spip_documents',\r
+                                               'id_objet' => $s['id_vignette']\r
+                                       ),\r
+                                       'data' => null\r
+                               )\r
+                       );\r
+                       $id_vignette = 0;\r
+               }\r
+\r
+               $arg = $data['vignette'];\r
+               check_upload_error($arg['error']);\r
+               // Ajout du document comme vignette\r
+\r
+               /**\r
+                * Méthode >= SPIP 3.0 \r
+                * ou SPIP 2.x + Mediatheque\r
+                */\r
+               if($ajouter_documents = charger_fonction('ajouter_documents','action',true)){\r
+                       $x = $ajouter_documents(null,array($arg),'', 0, 'vignette');\r
+                       $vignette = reset($x);\r
+                       if(intval($vignette))\r
+                               document_modifier($id, array('id_vignette'=>$vignette));\r
+                       else if($id_vignette)\r
+                               document_modifier($id, array('id_vignette'=>$id_vignette));\r
+               }\r
+               /**\r
+                * Méthode < SPIP 3.0\r
+                */\r
+               else if($ajouter_documents = charger_fonction('ajouter_documents','inc',true)){\r
+                       // On remet l'id_vignette a 0 si on l'a supprimé\r
+                       if($id_vignette) revision_document($s['id_document'], array('id_vignette'=>0));\r
+                       $x = $ajouter_documents($arg['tmp_name'], $arg['name'],'','', 'vignette', $id, $actifs);\r
+               }\r
+               \r
+       }else\r
+               // Suppression de la vignette ?\r
+               if ($wid = array_pop($ref)\r
+                       AND $_POST['content_'.$wid.'_vignette_supprimer'] == 'on') {\r
+                       if(is_numeric($s['id_vignette']) && ($s['id_vignette']>0)){\r
+                               // Suppression du document\r
+                               $vignette = sql_getfetsel('fichier', 'spip_documents', 'id_document='.intval($s['id_vignette']));\r
+                               if (@file_exists($f = get_spip_doc($vignette))) { \r
+                                       spip_log("efface $f"); \r
+                                       supprimer_fichier($f); \r
+                               }\r
+                               sql_delete('spip_documents', 'id_document='.intval($s['id_vignette']));\r
+                               sql_delete('spip_documents_liens',  'id_document='.intval($s['id_vignette']));\r
+\r
+                               pipeline('post_edition',\r
+                                       array(\r
+                                               'args' => array(\r
+                                                       'operation' => 'supprimer_document',\r
+                                                       'table' => 'spip_documents',\r
+                                                       'id_objet' => $s['id_vignette']\r
+                                               ),\r
+                                               'data' => null\r
+                                       )\r
+                               );\r
+\r
+                               // On remet l'id_vignette a 0\r
+                               revision_document($s['id_document'], array('id_vignette'=>0));\r
+                       }\r
+               }\r
+       return true;\r
+}\r
+\r
+\r
+function colonne_table($type, $col) {\r
+       list($distant,$table) = distant_table($type);\r
+       $nom_table = '';\r
+       if (!(($tabref = &crayons_get_table($table, $nom_table))\r
+               && isset($tabref['field'][$col])\r
+               && ($brut = $tabref['field'][$col]))) {\r
+                       return false;\r
+       }\r
+       $ana = explode(' ', $brut);\r
+       $sta = 0;\r
+       $sep = '';\r
+       $ret = array('brut' => $brut,\r
+               'type' => '', 'notnull' => false, 'long' => 0, 'def' => '');\r
+       foreach ($ana as $mot) {\r
+               switch ($sta) {\r
+                       case 0: $ret['type'] = ($mot = strtolower($mot));\r
+                       case 1: if ($mot[strlen($mot) - 1] == ')') {\r
+                                       $pos = strpos($mot, '(');\r
+                                       $ret['type'] = strtolower(substr($mot, 0, $pos++));\r
+                                       $vir = explode(',', substr($mot, $pos, -1));\r
+                                       if ($ret['type'] == 'enum') {\r
+                                               $ret['enum'] = $vir;\r
+                                       } elseif (count($vir) > 1) {\r
+                                               $ret['long'] = $vir;\r
+                                       } else {\r
+                                               $ret['long'] = $vir[0];\r
+                                       }\r
+                                       $sta = 1;\r
+                                       continue;\r
+                               }\r
+                               if (!$sta) {\r
+                                       $sta = 1;\r
+                                       continue;\r
+                               }\r
+                       case 2: switch (strtolower($mot)) {\r
+                               case 'not':\r
+                                       $sta = 3;\r
+                                       continue;\r
+                               case 'default':\r
+                                       $sta = 4;\r
+                                       continue;\r
+                               }\r
+                               continue;\r
+                       case 3:         $ret['notnull'] = strtolower($mot) == 'null';\r
+                               $sta = 2;\r
+                               continue;\r
+                       case 4: $df1 = strpos('"\'', $mot[0]) !== false? $mot[0] : '';\r
+                               $sta = 5;\r
+                       case 5: $ret['def'] .= $sep . $mot;\r
+                               if (!$df1) {\r
+                                       $sta = 2;\r
+                                       continue;\r
+                               }\r
+                               if ($df1 == $mot[strlen($mot) - 1]) {\r
+                                       $ret['def'] = substr($ret['def'], 1, -1);\r
+                                       $sta = 2;\r
+                               }\r
+                               $sep = ' ';\r
+                               continue;\r
+               }\r
+       }\r
+       return $ret;\r
+}\r
+\r
+\r
+/**\r
+ * Obtient le nom de la table ainsi que sa ou ses clés primaires\r
+ *\r
+ * @param string $type\r
+ *     Table sur laquelle s'applique le crayon.\r
+ *     Ce type peut contenir le nom d'un connecteur distant tel que `{connect}__{table}`\r
+ *\r
+ * @return array|bool\r
+ *     - false si on ne trouve pas de table ou de table ayant de clé primaire\r
+ *     - liste :\r
+ *     - - nom de la table sql\r
+ *     - - tableau des noms de clés primaires\r
+**/\r
+function crayons_get_table_name_and_primary($type) {\r
+       static $types = array();\r
+       if (isset($types[$type])) {\r
+               return $types[$type];\r
+       }\r
+\r
+       $nom_table = '';\r
+       if ($tabref = &crayons_get_table($type, $nom_table)\r
+         and ($tabid = explode(',', $tabref['key']['PRIMARY KEY'])))\r
+       {\r
+               return $types[$type] = array($nom_table, $tabid);\r
+       }\r
+       spip_log('crayons: table ' . $type . ' inconnue');\r
+       return $types[$type] = false;\r
+}\r
+\r
+\r
+function table_where($type, $id, $where_en_tableau = false) {\r
+\r
+\r
+       if (!$infos = crayons_get_table_name_and_primary($type)) {\r
+               return array(false, false);\r
+       }\r
+\r
+       list($nom_table, $tabid) = $infos;\r
+\r
+\r
+       if (is_scalar($id))\r
+               $id = explode('-', $id);\r
+       // sortie tableau pour sql_updateq\r
+       if ($where_en_tableau) {\r
+               $where = array();\r
+               foreach ($id as $idcol => $idval) {\r
+                       $where[] = '`' . (is_int($idcol) ? trim($tabid[$idcol]) : $idcol) . '`=' . sql_quote($idval);\r
+               }\r
+       // sinon sortie texte pour sql_query\r
+       } else {\r
+\r
+               $where = $and = '';\r
+               foreach ($id as $idcol => $idval) {\r
+                       $where .= $and . '`' . (is_int($idcol) ? trim($tabid[$idcol]) : $idcol) . '`=' . _q($idval);\r
+                       $and = ' AND ';\r
+               }\r
+       }\r
+       return array($nom_table, $where);\r
+}\r
+//     var_dump(colonne_table('forum', 'id_syndic')); die();\r
+\r
+function valeur_colonne_table_dist($type, $col, $id) {\r
+\r
+       // Table introuvable ou sans clé primaire\r
+       if (!$infos = crayons_get_table_name_and_primary($type)) {\r
+               return false;\r
+       }\r
+       $table = reset($infos);\r
+\r
+       $r = array();\r
+\r
+       // valeurs non SQL\r
+       foreach ($col as $champ) {\r
+               if (function_exists($f = 'valeur_champ_'.$table.'_'.$champ) OR function_exists($f = 'valeur_champ_'.$champ)) {\r
+                       $r[$champ] = $f($table, $id, $champ);\r
+                       $col = array_diff($col, array($champ));\r
+               }\r
+       }\r
+\r
+       // valeurs SQL\r
+       if (count($col)) {\r
+               list($distant, $table)   = distant_table($type);\r
+               list($nom_table, $where) = table_where($type, $id);\r
+\r
+               if ($s = spip_query(\r
+                               'SELECT `' . implode($col, '`, `') .\r
+                               '` FROM ' . $nom_table . ' WHERE ' . $where, $distant)\r
+                       AND $t = sql_fetch($s)){\r
+                               $r = array_merge($r, $t);\r
+               }\r
+       }\r
+\r
+       return $r;\r
+}\r
+\r
+/**\r
+ * Extrait la valeur d'une ou plusieurs colonnes d'une table\r
+ *\r
+ * @param string $table\r
+ *   Type d'objet de la table (article)\r
+ * @param string|array $col\r
+ *   Nom de la ou des colonnes (ps)\r
+ * @param string $id\r
+ *   Identifiant de l'objet\r
+ * @return array\r
+ *   Couples Nom de la colonne => Contenu de la colonne\r
+**/\r
+function valeur_colonne_table($table, $col, $id) {\r
+       if (!is_array($col))\r
+               $col = array($col);\r
+\r
+       if (function_exists($f = $table.'_valeur_colonne_table_dist')\r
+       OR function_exists($f = $table.'_valeur_colonne_table')\r
+       OR $f = 'valeur_colonne_table_dist')\r
+               return $f($table, $col, $id);\r
+}\r
+\r
+/**\r
+ * Extrait la valeur d'une configuration en meta\r
+ *\r
+ * Pour ces données, il n'y a toujours qu'une colonne (valeur),\r
+ * mais on gère l'enregistrement et la lecture via lire_config ou ecrire_config\r
+ * dès que l'on demande des sous parties d'une configuration.\r
+ *\r
+ * On ne retourne alors ici dans 'valeur' que la sous-partie demandée si\r
+ * c'est le cas.\r
+ *\r
+ * @param string $table\r
+ *   Nom de la table (meta)\r
+ * @param array $col\r
+ *   Nom des colonnes (valeur)\r
+ * @param string $id\r
+ *   Nom ou clé de configuration (descriptif_site ou demo__truc pour demo/truc)\r
+ * @return array\r
+ *   Couple valeur => Contenu de la configuration\r
+**/\r
+function meta_valeur_colonne_table_dist($table, $col, $id) {\r
+       // Certaines clés de configuration sont echapées ici (cf #EDIT_CONFIG{demo/truc})\r
+       $id = str_replace('__', '/', $id);\r
+\r
+       // Éviter de planter les vieux SPIP\r
+       if (false === strpos($id, '/')) {\r
+               $config = isset($GLOBALS['meta'][$id]) ? $GLOBALS['meta'][$id] : '';\r
+       // SPIP 3 ou Bonux 2 ou CFG\r
+       } else {\r
+               include_spip('inc/config');\r
+               $config =  lire_config($id, '');\r
+       }\r
+       return array('valeur' => $config);\r
+}\r
+\r
+\r
+function return_log($var) {\r
+       die(crayons_json_export(array('$erreur'=> var_export($var,true))));\r
+}\r
+\r
+function _U($texte, $params=array()) {\r
+       include_spip('inc/charsets');\r
+       return unicode2charset(html2unicode(_T($texte, $params)));\r
+}\r
+\r
+/**\r
+ * Obtenir la configuration des crayons\r
+ *\r
+ * @note wdgcfg = widget config :-)\r
+ * \r
+ * @return array\r
+ *     Couples : attribut => valeur\r
+**/\r
+function wdgcfg() {\r
+       $php = function_exists('crayons_config') ? crayons_config() : array();\r
+       include_spip('inc/meta');\r
+       lire_metas();\r
+       global $meta;\r
+       $metacrayons = empty($meta['crayons']) ? array() : unserialize($meta['crayons']);\r
+       $wdgcfg = array();\r
+       foreach (array(\r
+               'msgNoChange' => false,\r
+               'msgAbandon' => false,  /* etait: true */\r
+               'filet' => false,\r
+               'yellow_fade' => false,\r
+               'clickhide' => false /* etait: true */\r
+       )\r
+       as $cfgi => $def) {\r
+               $wdgcfg[$cfgi] = isset($php[$cfgi]) ? $php[$cfgi] :\r
+                       isset($metacrayons[$cfgi]) ? $metacrayons[$cfgi] : $def;\r
+       }\r
+       return $wdgcfg;\r
+}\r
+\r
+function &crayons_get_table($type, &$nom_table) {\r
+       list($distant,$table) = distant_table($type);\r
+       static $return = array();\r
+       static $noms = array();\r
+       if (!isset($return[$table])) {\r
+               $try = array(table_objet_sql($table), 'spip_'.table_objet($table), 'spip_' . $table . 's', $table . 's', 'spip_' . $table, $table);\r
+\r
+               // premiere possibilite (à partir de 1.9.3) : regarder directement la base\r
+               if (function_exists('sql_showtable')) {\r
+                       foreach ($try as $nom) {\r
+                               if ($q = sql_showtable($nom , !$distant , $distant)) {\r
+                                       $noms[$table] = $nom;\r
+                                       $return[$table] = $q;\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               // seconde, une heuristique 1.9.2\r
+               if (!isset($return[$table])) {\r
+                       include_spip('base/serial');\r
+                       include_spip('base/auxiliaires');\r
+                       include_spip('public/parametrer');\r
+                       foreach(array('tables_principales', 'tables_auxiliaires') as $categ) {\r
+                               foreach ($try as $nom) {\r
+                                       if (isset($GLOBALS[$categ][$nom])) {\r
+                                               $noms[$table] = $nom;\r
+                                               $return[$table] = & $GLOBALS[$categ][$nom];\r
+                                               break 2;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       $nom_table = $noms[$table];\r
+       return $return[$table];\r
+}\r
+\r
+function distant_table($type) {\r
+       //separation $type en $distant $table\r
+       //separateur double underscore "__"\r
+       strstr($type,'__')? list($distant,$table) = explode('__',$type) : list($distant,$table) = array(False,$type);\r
+       return array($distant,$table);\r
+}\r
+?>\r