[SPIP] ~maj SPIP v3.0.17 --> v3.0.19
[lhc/web/clavette_www.git] / www / plugins-dist / forum / inc / forum.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2014 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
12
13 if (!defined("_ECRIRE_INC_VERSION")) return;
14 include_spip('inc/actions');
15
16 /**
17 * recuperer le critere SQL qui selectionne nos forums
18 * http://code.spip.net/@critere_statut_controle_forum
19 *
20 * @param string $type
21 * @param int|array $id_secteur
22 * @param string $recherche
23 * @return array
24 */
25 function critere_statut_controle_forum($type, $id_secteur=0, $recherche='') {
26
27 if (!$id_secteur) {
28 $from = 'spip_forum AS F';
29 $where = "";
30 $and = "";
31 } else {
32 if (!is_array($id_secteur)){
33 $id_secteur = explode(',',$id_secteur);
34 }
35 $from = 'spip_forum AS F, spip_articles AS A';
36 $where = sql_in("A.id_secteur",$id_secteur)." AND F.objet='article' AND F.id_objet=A.id_article";
37 $and = ' AND ';
38 }
39
40 switch ($type) {
41 case 'public':
42 $and .= "F.statut IN ('publie', 'off', 'prop', 'spam') AND F.texte!=''";
43 break;
44 case 'prop':
45 $and .= "F.statut='prop'";
46 break;
47 case 'spam':
48 $and .= "F.statut='spam'";
49 break;
50 case 'interne':
51 $and .= "F.statut IN ('prive', 'privrac', 'privoff', 'privadm') AND F.texte!=''";
52 break;
53 case 'vide':
54 $and .= "F.statut IN ('publie', 'off', 'prive', 'privrac', 'privoff', 'privadm') AND F.texte=''";
55 break;
56 default:
57 $where = '0=1';
58 $and ='';
59 break;
60 }
61
62 if ($recherche) {
63 # recherche par IP
64 if (preg_match(',^\d+\.\d+\.(\*|\d+\.(\*|\d+))$,', $recherche)) {
65 $and .= " AND ip LIKE ".sql_quote(str_replace('*', '%', $recherche));
66 } else {
67 include_spip('inc/rechercher');
68 if ($a = recherche_en_base($recherche, 'forum'))
69 $and .= " AND ".sql_in('id_forum',
70 array_keys(array_pop($a)));
71 else
72 $and .= " AND 0=1";
73 }
74 }
75
76 return array($from, "$where$and");
77 }
78
79 // Index d'invalidation des forums
80 // obsolete, remplace par l'appel systematique a 2 invalideurs :
81 // - forum/id_forum
82 // - objet/id_objet
83 // http://code.spip.net/@calcul_index_forum
84 function calcul_index_forum($objet,$id_objet) {
85 return substr($objet,0,1).$id_objet;
86 }
87
88 //
89 // Recalculer tous les threads
90 //
91 // http://code.spip.net/@calculer_threads
92 function calculer_threads() {
93 // fixer les id_thread des debuts de discussion
94 sql_update('spip_forum', array('id_thread'=>'id_forum'), "id_parent=0");
95 // reparer les messages qui n'ont pas l'id_secteur de leur parent
96 do {
97 $discussion = "0";
98 $precedent = 0;
99 $r = sql_select("fille.id_forum AS id, maman.id_thread AS thread", 'spip_forum AS fille, spip_forum AS maman', "fille.id_parent = maman.id_forum AND fille.id_thread <> maman.id_thread",'', "thread");
100 while ($row = sql_fetch($r)) {
101 if ($row['thread'] == $precedent)
102 $discussion .= "," . $row['id'];
103 else {
104 if ($precedent)
105 sql_updateq("spip_forum", array("id_thread" => $precedent), "id_forum IN ($discussion)");
106 $precedent = $row['thread'];
107 $discussion = $row['id'];
108 }
109 }
110 sql_updateq("spip_forum", array("id_thread" => $precedent), "id_forum IN ($discussion)");
111 } while ($discussion != "0");
112 }
113
114 // Calculs des URLs des forums (pour l'espace public)
115 // http://code.spip.net/@racine_forum
116 function racine_forum($id_forum){
117 if (!$id_forum = intval($id_forum)) return false;
118
119 $row = sql_fetsel("id_parent, objet, id_objet, id_thread", "spip_forum", "id_forum=".$id_forum);
120
121 if (!$row) return false;
122
123 if ($row['id_parent']
124 AND $row['id_thread'] != $id_forum) // eviter boucle infinie
125 return racine_forum($row['id_thread']);
126
127 return array($row['objet'], $row['id_objet'], $id_forum);
128 }
129
130
131 // http://code.spip.net/@parent_forum
132 function parent_forum($id_forum) {
133 if (!$id_forum = intval($id_forum)) return;
134 $row = sql_fetsel("id_parent, objet, id_objet", "spip_forum", "id_forum=".$id_forum);
135 if(!$row) return array();
136 if ($row['id_parent'])
137 return array('forum', $row['id_parent']);
138 else
139 return array($row['objet'], $row['id_objet']);
140 }
141
142
143 /**
144 * Pour compatibilite : remplacer les appels par son contenu
145 *
146 * @param unknown_type $id_forum
147 * @param unknown_type $args
148 * @param unknown_type $ancre
149 * @return unknown
150 */
151 function generer_url_forum_dist($id_forum, $args='', $ancre='') {
152 $generer_url_forum = charger_fonction('generer_url_forum','urls');
153 return $generer_url_forum($id_forum, $args, $ancre);
154 }
155
156
157 // http://code.spip.net/@generer_url_forum_parent
158 function generer_url_forum_parent($id_forum) {
159 if ($id_forum = intval($id_forum)) {
160 list($type, $id) = parent_forum($id_forum);
161 if ($type)
162 return generer_url_entite($id, $type);
163 }
164 return '';
165 }
166
167
168 // Quand on edite un forum, on tient a conserver l'original
169 // sous forme d'un forum en reponse, de statut 'original'
170 // http://code.spip.net/@conserver_original
171 function conserver_original($id_forum) {
172 $s = sql_fetsel("id_forum", "spip_forum", "id_parent=".intval($id_forum)." AND statut='original'");
173
174 if ($s) return ''; // pas d'erreur
175
176 // recopier le forum
177 $t = sql_fetsel("*", "spip_forum", "id_forum=".intval($id_forum));
178
179 if ($t) {
180 unset($t['id_forum']);
181 $id_copie = sql_insertq('spip_forum', $t);
182 if ($id_copie) {
183 sql_updateq('spip_forum', array('id_parent'=> $id_forum, 'statut'=>'original'), "id_forum=$id_copie");
184 return ''; // pas d'erreur
185 }
186 }
187
188 return '&erreur';
189 }
190
191 // appelle conserver_original(), puis modifie le contenu via l'API inc/modifier
192 // http://code.spip.net/@enregistre_et_modifie_forum
193 function enregistre_et_modifie_forum($id_forum, $c=false) {
194 if ($err = conserver_original($id_forum)) {
195 spip_log("erreur de sauvegarde de l'original, $err");
196 return;
197 }
198
199 include_spip('action/editer_forum');
200 return revision_forum($id_forum, $c);
201 }
202
203
204 /**
205 * Trouver le titre d'un objet publie
206 * @param string $objet
207 * @param int $id_objet
208 * @param int $id_forum
209 * @param bool $publie
210 * @return bool|string
211 */
212 function forum_recuperer_titre_dist($objet, $id_objet, $id_forum=0, $publie = true) {
213 include_spip('inc/filtres');
214 $titre = "";
215
216 if ($f = charger_fonction($objet.'_forum_extraire_titre', 'inc', true)){
217 $titre = $f($id_objet);
218 }
219 else {
220 include_spip('base/objets');
221 if ($publie AND !objet_test_si_publie($objet, $id_objet))
222 return false;
223
224 $titre = generer_info_entite($id_objet, $objet,'titre','*');
225 }
226
227 if ($titre AND $id_forum){
228 $titre_m = sql_getfetsel('titre', 'spip_forum', "id_forum = " . intval($id_forum));
229 if (!$titre_m) {
230 return false; // URL fabriquee
231 }
232 $titre = $titre_m;
233 }
234
235 $titre = supprimer_numero($titre);
236 $titre = str_replace('~', ' ', extraire_multi($titre));
237
238 return $titre;
239 }
240
241
242 /**
243 * Retourne pour un couple objet/id_objet donne
244 * de quelle maniere les forums sont acceptes dessus
245 * non: pas de forum
246 * pos: a posteriori, acceptes et eventuellements moderes ensuite
247 * pri: a priori, doivent etre valides par un admin
248 * abo: les personnes doivent au prealable etre identifiees
249 *
250 * http://code.spip.net/@controler_forum
251 *
252 * @param string $objet
253 * objet a tester
254 * @param int $id_objet
255 * identifiant de l'objet
256 * @return string
257 * chaine de 3 caractere parmi 'non','pos','pri','abo'
258 */
259 function controler_forum($objet, $id_objet) {
260 // Valeur par defaut
261 $accepter_forum = $GLOBALS['meta']["forums_publics"];
262
263 // il y a un cas particulier pour l'acceptation de forum d'article...
264 if ($f = charger_fonction($objet . '_accepter_forums_publics', 'inc', true)){
265 $accepter_forum = $f($id_objet);
266 }
267
268 return substr($accepter_forum, 0, 3);
269 }
270
271
272 /**
273 * Verifier la presence du jeton de secu post previsu
274 * http://code.spip.net/@forum_insert_noprevisu
275 * @return bool
276 */
277 function forum_insert_noprevisu(){
278 // simuler une action venant de l'espace public
279 // pour se conformer au cas general.
280 set_request('action', 'ajout_forum');
281 // Creer une session s'il n'y en a pas (cas du postage sans cookie)
282 $securiser_action = charger_fonction('securiser_action', 'inc');
283 $arg = $securiser_action();
284
285 $file = _DIR_TMP ."forum_" . preg_replace('/[^0-9]/', '', $arg) .".lck";
286 if (!file_exists($file)) {
287 # ne pas tracer cette erreur, peut etre due a un double POST
288 # tracer_erreur_forum('session absente');
289 return true;
290 }
291 unlink($file);
292
293 // antispam : si le champ au nom aleatoire verif_$hash n'est pas 'ok'
294 // on meurt
295 if (_request('verif_'._request('hash')) != 'ok') {
296 tracer_erreur_forum('champ verif manquant');
297 return true;
298 }
299 return false;
300 }
301
302
303 /**
304 * recuperer tous les objets dont on veut pouvoir obtenir l'identifiant
305 * directement dans l'environnement
306 *
307 * @return array
308 */
309 function forum_get_objets_depuis_env() {
310 static $objets = null;
311 if ($objets === null) {
312 // on met une cle (le type d'objet) pour qu'un appel du pipeline
313 // puisse facilement soustraire un objet qu'il ne veut pas avec
314 // unset($objets['rubrique']) par exemple.
315 $objets = pipeline('forum_objets_depuis_env', array(
316 'article' => id_table_objet('article'),
317 'rubrique' => id_table_objet('rubrique'),
318 'site' => id_table_objet('site'),
319 'breve' => id_table_objet('breve')
320 ));
321 asort($objets);
322 }
323
324 return $objets;
325 }
326
327
328 // http://code.spip.net/@reduce_strlen
329 function reduce_strlen($n, $c)
330 {
331 return $n - (is_string($c) ? strlen($c) : 0);
332 }
333 ?>