source: spip-zone/_plugins_/crayons/trunk/inc/crayons.php @ 118926

Last change on this file since 118926 was 118926, checked in by gouz@…, 8 months ago

modification du controleur/vue crayon/traduction pour enregistrement effectif de la traduction proposée si inexistante

File size: 17.0 KB
Line 
1<?php
2/**
3 * Crayons
4 * plugin for spip
5 * (c) Fil, toggg 2006-2019
6 * licence GPL
7 */
8
9if (!defined('_ECRIRE_INC_VERSION')) {
10        return;
11}
12
13define('_PREG_CRAYON', ',crayon\b[^<>\'"]+?\b((\w+)-(\w+)-(\w+(?:-\w+)*))\b,');
14
15// Autoriser les crayons sur les tables non SPIP ?
16// Par defaut : oui (pour les admins complets, si autoriser_defaut_dist()) ;
17// mettre a false en cas de mutualisation par prefixe de table,
18// sinon on ne peut pas garantir que les sites sont hermetiques
19if (!defined('_CRAYONS_TABLES_EXTERNES')) {
20        define('_CRAYONS_TABLES_EXTERNES', true);
21}
22
23// Autorisations non prevues par le core
24include_spip('inc/autoriser');
25
26include_spip('inc/crayons-json');
27
28if (!function_exists('autoriser_meta_modifier_dist')) {
29/**
30 * Autorisation d'éditer les configurations dans spip_meta
31 *
32 * Les admins complets OK pour certains champs,
33 * Sinon, il faut être webmestre
34 *
35 * @note
36 *  Attention sur les SPIP < 11515 (avant 04/2008) inc/autoriser
37 *  passe seulement intval($id) alors qu'ici la cle est une chaine...
38 *
39 * @param  string $faire Action demandée
40 * @param  string $type  Type d'objet sur lequel appliquer l'action
41 * @param  int    $id    Identifiant de l'objet
42 * @param  array  $qui   Description de l'auteur demandant l'autorisation
43 * @param  array  $opt   Options de cette autorisation
44 * @return bool          true s'il a le droit, false sinon
45**/
46function autoriser_meta_modifier_dist($faire, $type, $id, $qui, $opt) {
47        // Certaines cles de configuration sont echapées ici (cf #EDIT_CONFIG{demo/truc})
48        // $id = str_replace('__', '/', $id);
49        if (in_array($id, array('nom_site', 'slogan_site', 'descriptif_site', 'email_webmaster'))) {
50                return autoriser('configurer', null, null, $qui);
51        } else {
52                return autoriser('webmestre', null, null, $qui);
53        }
54}
55}
56
57// table spip_messages, la c'est tout simplement non (peut mieux faire,
58// mais c'est a voir dans le core/organiseur ou dans autorite)
59if (defined('_DIR_PLUGIN_ORGANISEUR')) {
60        include_spip('organiseur_autoriser');
61}
62
63if (!function_exists('autoriser_message_modifier_dist')) {
64        function autoriser_message_modifier_dist($faire, $type, $id, $qui, $opt) {
65                return false;
66        }
67}
68
69// Autoriser l'usage des crayons ?
70function autoriser_crayonner_dist($faire, $type, $id, $qui, $opt) {
71        // Le type pouvant etre une table, verifier les autoriser('modifier')
72        // correspondant ; ils demandent le nom de l'objet: spip_articles => article
73        // ex: spip_articles => 'article'
74        $type = preg_replace(',^spip_(.*?)s?$,', '\1', $type);
75        if (strlen($GLOBALS['table_prefix'])) {
76                $type = preg_replace(',^'.$GLOBALS['table_prefix'].'_(.*?)s?$,', '\1', $type);
77        }
78
79        // Tables non SPIP ? Si elles sont interdites il faut regarder
80        // quelle table on appelle, et verifier si elle est "interne"
81        if (!_CRAYONS_TABLES_EXTERNES) {
82                include_spip('base/serial');
83                include_spip('base/auxiliaires');
84                include_spip('public/parametrer');
85                if (!isset($GLOBALS['tables_principales']['spip_'.table_objet($type)])
86                        and !isset($GLOBALS['tables_auxiliaires']['spip_'.table_objet($type)])) {
87                        return false;
88                }
89        }
90
91        // Traduire le modele en liste de champs
92        if (isset($opt['modele'])) {
93                $opt['champ'] = $opt['modele'];
94        }
95
96        // Pour un auteur, si le champ est statut ou email, signaler l'option
97        // ad hoc (cf. inc/autoriser)
98        if ($type == 'auteur'
99                and in_array($opt['champ'], array('statut', 'email'))) {
100                $opt[$opt['champ']] = true;
101        }
102
103        return (
104                 autoriser('modifier', $type, $id, $qui, $opt)
105        );
106}
107
108// Si un logo est demande, on renvoie la date dudit logo (permettra de gerer
109// un "modifie par ailleurs" si la date a change, rien de plus)
110function valeur_champ_logo($table, $id, $champ) {
111        $chercher_logo = charger_fonction('chercher_logo', 'inc');
112        $on = $chercher_logo($id, id_table_objet($table), 'on');
113        return $on ? filemtime($on[0]) : false;
114}
115
116// Idem : si un doc est demande, on renvoie la date du doc
117function valeur_champ_document($table, $id, $champ) {
118        return sql_getfetsel('date', 'spip_documents', 'id_document=' . intval($id));
119}
120
121function valeur_champ_vignette($table, $id, $champ) {
122        $vignette = sql_getfetsel('id_vignette', 'spip_documents', 'id_document=' . intval($id));
123        if (is_numeric($vignette) && ($vignette > 0)) {
124                $date = sql_getfetsel('date', 'spip_documents', 'id_document=' . intval($vignette));
125        }
126        return $date ? $date : false;
127}
128// cette fonction de revision recoit le fichier upload a passer en logo
129// en reference : le nom du widget, pour aller chercher d'autres donnees
130// (ex: supprimer)
131function logo_revision($id, $file, $type, $ref) {
132        $chercher_logo = charger_fonction('chercher_logo', 'inc');
133        $_id_objet = id_table_objet($type);
134
135        // Chargement d'un nouveau logo ?
136        if ($file['logo']) {
137                define('FILE_UPLOAD', true); // message pour crayons_json_export :(
138
139                include_spip('action/editer_logo');
140                logo_modifier($type, $id, 'on', $file['logo']);
141        } else {
142                // Suppression du logo ?
143                if ($wid = array_pop($ref)
144                        and $_POST['content_'.$wid.'_logo_supprimer'] == 'on') {
145                        include_spip('action/editer_logo');
146                        logo_supprimer($type, $id, 'on');
147                }
148        }
149
150        // Reduire le logo ?
151        if (is_array($cfg = @unserialize($GLOBALS['meta']['crayons']))
152                and $max = intval($cfg['reduire_logo'])) {
153                $on = $chercher_logo($id, $_id_objet, 'on');
154                include_spip('inc/filtres');
155                @copy($on[0], $temp = _DIR_VAR . 'tmp' . rand(0, 999) . '.' . $on[3]);
156                $img1 = filtrer('image_reduire', $temp, $max);
157                $img2 = preg_replace(',[?].*,', '', extraire_attribut($img1, 'src'));
158                if (@file_exists($img2)
159                        and $img2 !=  $temp) {
160                        include_spip('action/editer_logo');
161                        logo_modifier($type, $id, 'on', $img2);
162                }
163                @unlink($temp);
164        }
165
166        return true;
167}
168
169
170// cette fonction de revision recoit le fichier upload a passer en document
171function document_fichier_revision($id, $data, $type, $ref) {
172
173        if (!$t = sql_fetsel('*', 'spip_documents', 'id_document=' . intval($id))) {
174                return false;
175        }
176
177        /*
178        // Envoi d'une URL de document distant ?
179        // TODO: verifier l'extension distante, sinon tout explose
180        if ($data['fichier']
181        AND preg_match(',^(https?|ftp)://.+,', $data['fichier'])) {
182                include_spip('inc/modifier');
183                modifier_contenu('document', $id,
184                        array('champs' => array('fichier', 'distant')),
185                        array('fichier' => $data['fichier'], 'distant' => 'oui')
186                );
187                return true;
188        }
189        else
190        */
191
192        // Chargement d'un nouveau doc ?
193        if ($data['document']){
194                $arg = $data['document'];
195                /**
196                 * Méthode >= SPIP 3.0
197                 * ou SPIP 2.x + Mediathèque
198                 */
199                $ajouter_documents = charger_fonction('ajouter_documents', 'action');
200                $actifs = $ajouter_documents($id, array($arg), '', 0, $t['mode']);
201                $x = reset($actifs);
202                if (is_numeric($x)){
203                        return true;
204                } else {
205                        return false;
206                }
207        }
208}
209
210// cette fonction de revision soit supprime la vignette d'un document,
211// soit recoit le fichier upload a passer ou remplacer la vignette du document
212function vignette_revision($id, $data, $type, $ref) {
213        if (!$s = sql_fetsel('id_document,id_vignette', 'spip_documents', 'id_document = '.intval($id))) {
214                return false;
215        }
216
217        include_spip('inc/modifier');
218        include_spip('inc/documents');
219        include_spip('action/editer_document');//pour revision_document
220        // Chargement d'un nouveau doc ?
221        if ($data['vignette']) {
222                define('FILE_UPLOAD', true);
223                if (is_numeric($s['id_vignette']) and ($s['id_vignette'] > 0)) {
224                        spip_log('suppression de la vignette');
225                        // Suppression du document
226                        $vignette = sql_getfetsel('fichier', 'spip_documents', 'id_document='.intval($s['id_vignette']));
227                        if (@file_exists($f = get_spip_doc($vignette))) {
228                                spip_log("efface $f");
229                                supprimer_fichier($f);
230                        }
231                        sql_delete('spip_documents', 'id_document='.intval($s['id_vignette']));
232                        sql_delete('spip_documents_liens', 'id_document='.intval($s['id_vignette']));
233
234                        pipeline(
235                                'post_edition',
236                                array(
237                                        'args' => array(
238                                                'operation' => 'supprimer_document',
239                                                'table' => 'spip_documents',
240                                                'id_objet' => $s['id_vignette']
241                                        ),
242                                        'data' => null
243                                )
244                        );
245                        $id_vignette = 0;
246                }
247
248                $arg = $data['vignette'];
249                check_upload_error($arg['error']);
250
251                // Ajout du document comme vignette
252                $ajouter_documents = charger_fonction('ajouter_documents', 'action');
253                $x = $ajouter_documents(null,array($arg),'', 0, 'vignette');
254                $vignette = reset($x);
255                if (intval($vignette)) {
256                        document_modifier($id, array('id_vignette'=>$vignette));
257                } elseif ($id_vignette) {
258                        document_modifier($id, array('id_vignette'=>$id_vignette));
259                }
260        } elseif ($wid = array_pop($ref)
261                and $_POST['content_'.$wid.'_vignette_supprimer'] == 'on') {
262                if (is_numeric($s['id_vignette']) and ($s['id_vignette']>0)) {
263                        // Suppression du document
264                        $vignette = sql_getfetsel('fichier', 'spip_documents', 'id_document='.intval($s['id_vignette']));
265                        if (@file_exists($f = get_spip_doc($vignette))) {
266                                spip_log("efface $f");
267                                supprimer_fichier($f);
268                        }
269                        sql_delete('spip_documents', 'id_document='.intval($s['id_vignette']));
270                        sql_delete('spip_documents_liens', 'id_document = ' . intval($s['id_vignette']));
271
272                        pipeline(
273                                'post_edition',
274                                array(
275                                        'args' => array(
276                                                'operation' => 'supprimer_document',
277                                                'table' => 'spip_documents',
278                                                'id_objet' => $s['id_vignette']
279                                        ),
280                                        'data' => null
281                                )
282                        );
283
284                        // On remet l'id_vignette a 0
285                        document_modifier($s['id_document'], array('id_vignette'=>0));
286                }
287        }
288        return true;
289}
290
291
292function colonne_table($type, $col) {
293        list($distant,$table) = distant_table($type);
294        $nom_table = '';
295        if (!(($tabref = &crayons_get_table($table, $nom_table))
296                && isset($tabref['field'][$col])
297                && ($brut = $tabref['field'][$col]))) {
298                        return false;
299        }
300        $ana = explode(' ', $brut);
301        $sta = 0;
302        $sep = '';
303        $ret = array('brut' => $brut,
304                'type' => '', 'notnull' => false, 'long' => 0, 'def' => '');
305        foreach ($ana as $mot) {
306                switch ($sta) {
307                        case 0:
308                                $ret['type'] = ($mot = strtolower($mot));
309                        case 1:
310                                if ($mot[strlen($mot) - 1] == ')') {
311                                        $pos = strpos($mot, '(');
312                                        $ret['type'] = strtolower(substr($mot, 0, $pos++));
313                                        $vir = explode(',', substr($mot, $pos, -1));
314                                        if ($ret['type'] == 'enum') {
315                                                $ret['enum'] = $vir;
316                                        } elseif (count($vir) > 1) {
317                                                $ret['long'] = $vir;
318                                        } else {
319                                                $ret['long'] = $vir[0];
320                                        }
321                                        $sta = 1;
322                                        break;
323                                }
324                                if (!$sta) {
325                                        $sta = 1;
326                                        break;
327                                }
328                        case 2:
329                                switch (strtolower($mot)) {
330                                        case 'not':
331                                                $sta = 3;
332                                                break;
333                                        case 'default':
334                                                $sta = 4;
335                                                break;
336                                }
337                                break;
338                        case 3:
339                                $ret['notnull'] = strtolower($mot) == 'null';
340                                $sta = 2;
341                                break;
342                        case 4:
343                                $df1 = strpos('"\'', $mot[0]) !== false? $mot[0] : '';
344                                $sta = 5;
345                        case 5:
346                                $ret['def'] .= $sep . $mot;
347                                if (!$df1) {
348                                        $sta = 2;
349                                        break;
350                                }
351                                if ($df1 == $mot[strlen($mot) - 1]) {
352                                        $ret['def'] = substr($ret['def'], 1, -1);
353                                        $sta = 2;
354                                }
355                                $sep = ' ';
356                                break;
357                }
358        }
359        return $ret;
360}
361
362
363/**
364 * Obtient le nom de la table ainsi que sa ou ses clés primaires
365 *
366 * @param string $type
367 *     Table sur laquelle s'applique le crayon.
368 *     Ce type peut contenir le nom d'un connecteur distant tel que `{connect}__{table}`
369 *
370 * @return array|bool
371 *     - false si on ne trouve pas de table ou de table ayant de clé primaire
372 *     - liste :
373 *     - - nom de la table sql
374 *     - - tableau des noms de clés primaires
375**/
376function crayons_get_table_name_and_primary($type) {
377        static $types = array();
378        if (isset($types[$type])) {
379                return $types[$type];
380        }
381
382        $nom_table = '';
383        if ($tabref = &crayons_get_table($type, $nom_table)
384                and ($tabid = explode(',', $tabref['key']['PRIMARY KEY']))) {
385                return $types[$type] = array($nom_table, $tabid);
386        }
387        spip_log('crayons: table ' . $type . ' inconnue');
388        return $types[$type] = false;
389}
390
391
392function table_where($type, $id, $where_en_tableau = false) {
393        if (!$infos = crayons_get_table_name_and_primary($type)) {
394                return array(false, false);
395        }
396
397        list($nom_table, $tabid) = $infos;
398
399        if (is_scalar($id)) {
400                $id = explode('-', $id);
401        }
402        // sortie tableau pour sql_updateq
403        if ($where_en_tableau) {
404                $where = array();
405                foreach ($id as $idcol => $idval) {
406                        $where[] = '`' . (is_int($idcol) ? trim($tabid[$idcol]) : $idcol) . '`=' . sql_quote($idval);
407                }
408        // sinon sortie texte pour sql_query
409        } else {
410                $where = $and = '';
411                foreach ($id as $idcol => $idval) {
412                        $where .= $and . '`' . (is_int($idcol) ? trim($tabid[$idcol]) : $idcol) . '`=' . _q($idval);
413                        $and = ' AND ';
414                }
415        }
416        return array($nom_table, $where);
417}
418//      var_dump(colonne_table('forum', 'id_syndic')); die();
419
420function valeur_colonne_table_dist($type, $col, $id) {
421
422        // Table introuvable ou sans clé primaire
423        if (!$infos = crayons_get_table_name_and_primary($type)) {
424                return false;
425        }
426        $table = reset($infos);
427
428        $r = array();
429
430        // valeurs non SQL
431        foreach ($col as $champ) {
432                if (function_exists($f = 'valeur_champ_'.$table.'_'.$champ)
433                        or function_exists($f = 'valeur_champ_'.$champ)) {
434                        $r[$champ] = $f($table, $id, $champ);
435                        $col = array_diff($col, array($champ));
436                }
437        }
438
439        // valeurs SQL
440        if (count($col)) {
441                list($distant, $table)   = distant_table($type);
442                list($nom_table, $where) = table_where($type, $id);
443
444                if ($s = spip_query(
445                        'SELECT `' . implode($col, '`, `') .
446                        '` FROM ' . $nom_table . ' WHERE ' . $where,
447                        $distant
448                ) and $t = sql_fetch($s)) {
449                                $r = array_merge($r, $t);
450                }
451        }
452
453        return $r;
454}
455
456/**
457 * Extrait la valeur d'une ou plusieurs colonnes d'une table
458 *
459 * @param string $table
460 *   Type d'objet de la table (article)
461 * @param string|array $col
462 *   Nom de la ou des colonnes (ps)
463 * @param string $id
464 *   Identifiant de l'objet
465 * @return array
466 *   Couples Nom de la colonne => Contenu de la colonne
467**/
468function valeur_colonne_table($table, $col, $id) {
469        if (!is_array($col)) {
470                $col = array($col);
471        }
472
473        if (function_exists($f = $table . '_valeur_colonne_table_dist')
474                or function_exists($f = $table.'_valeur_colonne_table')
475                or $f = 'valeur_colonne_table_dist') {
476                return $f($table, $col, $id);
477        }
478}
479
480/**
481 * Extrait la valeur d'une configuration en meta
482 *
483 * Pour ces données, il n'y a toujours qu'une colonne (valeur),
484 * mais on gère l'enregistrement et la lecture via lire_config ou ecrire_config
485 * dès que l'on demande des sous parties d'une configuration.
486 *
487 * On ne retourne alors ici dans 'valeur' que la sous-partie demandée si
488 * c'est le cas.
489 *
490 * @param string $table
491 *   Nom de la table (meta)
492 * @param array $col
493 *   Nom des colonnes (valeur)
494 * @param string $id
495 *   Nom ou clé de configuration (descriptif_site ou demo__truc pour demo/truc)
496 * @return array
497 *   Couple valeur => Contenu de la configuration
498**/
499function meta_valeur_colonne_table_dist($table, $col, $id) {
500        // Certaines clés de configuration sont echapées ici (cf #EDIT_CONFIG{demo/truc})
501        $id = str_replace('__', '/', $id);
502
503        include_spip('inc/config');
504        $config =  lire_config($id, '');
505
506        return array('valeur' => $config);
507}
508
509/**
510 * Extrait la valeur d'une chaine de langue
511 *
512 * @param string $table
513 *   Nom de la """table""" (traduction)
514 * @param array $motifs
515 *   Motifs a traduire
516 * @param string $module
517 *   Module de langue sous la forme module_lang, ex local_fr
518 * @return array
519 *   Couple motif_chaine_de_langue => valeur traduite
520**/
521function traduction_valeur_colonne_table_dist($table, $motifs, $module) {
522        $lang = substr($module,-2);
523        $mod = substr($module,0,-3);
524        $valeur = _T("$mod:$motifs[0]", array('spip_lang'=>$lang), array('force'=>false));
525        // valeur vide si traduction trouvée dans la langue du site
526        if ( $lang != $GLOBALS['meta']['langue_site'] && $valeur == _T("$mod:$motifs[0]", array('spip_lang'=>$GLOBALS['meta']['langue_site'])) ){
527                $valeur='';
528        }
529        return array($motifs[0] => $valeur);
530}
531
532
533function return_log($var) {
534        die(crayons_json_encode(array('$erreur'=> var_export($var, true))));
535}
536
537function _U($texte, $params = array()) {
538        include_spip('inc/charsets');
539        return unicode2charset(html2unicode(_T($texte, $params)));
540}
541
542/**
543 * Obtenir la configuration des crayons
544 *
545 * @note wdgcfg = widget config :-)
546 *
547 * @return array
548 *     Couples : attribut => valeur
549**/
550function wdgcfg() {
551        $php = function_exists('crayons_config') ? crayons_config() : array();
552        include_spip('inc/meta');
553        lire_metas();
554        global $meta;
555        $metacrayons = empty($meta['crayons']) ? array() : unserialize($meta['crayons']);
556        $wdgcfg = array();
557        foreach (array(
558                'msgNoChange' => false,
559                'msgAbandon' => false,  /* etait: true */
560                'yellow_fade' => false,
561                'clickhide' => false /* etait: true */
562        ) as $cfgi => $def) {
563                $wdgcfg[$cfgi] = isset($php[$cfgi]) ? $php[$cfgi] :
564                        isset($metacrayons[$cfgi]) ? $metacrayons[$cfgi] : $def;
565        }
566        return $wdgcfg;
567}
568
569function &crayons_get_table($type, &$nom_table) {
570        list($distant,$table) = distant_table($type);
571        static $return = array();
572        static $noms = array();
573        if (!isset($return[$table])) {
574                $try = array(table_objet_sql($table), 'spip_'.table_objet($table), 'spip_' . $table . 's', $table . 's', 'spip_' . $table, $table);
575
576                foreach ($try as $nom) {
577                        if ($q = sql_showtable($nom, !$distant, $distant)) {
578                                $noms[$table] = $nom;
579                                $return[$table] = $q;
580                                break;
581                        }
582                }
583        }
584
585        $nom_table = $noms[$table];
586        return $return[$table];
587}
588
589function distant_table($type) {
590        //separation $type en $distant $table
591        //separateur double underscore "__"
592        strstr($type, '__') ? list($distant,$table) = explode('__', $type) : list($distant, $table) = array(false, $type);
593        return array($distant,$table);
594}
Note: See TracBrowser for help on using the repository browser.