PageRenderTime 42ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/spip/ecrire/inc/revisions.php

https://github.com/eyeswebcrea/espace-couture-sittler.fr
PHP | 683 lines | 461 code | 100 blank | 122 comment | 96 complexity | ff0d58de764da7a11747669af74d5e73 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-3.0
  1. <?php
  2. /***************************************************************************\
  3. * SPIP, Systeme de publication pour l'internet *
  4. * *
  5. * Copyright (c) 2001-2011 *
  6. * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
  7. * *
  8. * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
  9. * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
  10. \***************************************************************************/
  11. if (!defined('_ECRIRE_INC_VERSION')) return;
  12. $GLOBALS['agregation_versions'] = 10;
  13. define('_INTERVALLE_REVISIONS', 3600); // intervalle de temps separant deux revisions par un meme auteur
  14. // http://doc.spip.org/@separer_paras
  15. function separer_paras($texte, $paras = "") {
  16. if (!$paras) $paras = array();
  17. while (preg_match("/(\r\n?){2,}|\n{2,}/", $texte, $regs)) {
  18. $p = strpos($texte, $regs[0]) + strlen($regs[0]);
  19. $paras[] = substr($texte, 0, $p);
  20. $texte = substr($texte, $p);
  21. }
  22. if ($texte) $paras[] = $texte;
  23. return $paras;
  24. }
  25. // http://doc.spip.org/@replace_fragment
  26. function replace_fragment($id_article, $version_min, $version_max, $id_fragment, $fragment) {
  27. $fragment = serialize($fragment);
  28. $compress = 0;
  29. // pour le portage en PG il faut l'equivalente au mysql_escape_string
  30. // et deporter son appel dans les fonctions d'abstraction.
  31. if (function_exists('gzcompress')
  32. AND $GLOBALS['connexions'][0]['type'] == 'mysql') {
  33. $s = gzcompress($fragment);
  34. if (strlen($s) < strlen($fragment)) {
  35. # spip_log("gain gz: ".intval(100 - 100 * strlen($s) / strlen($fragment)));
  36. $compress = 1;
  37. $fragment = $s;
  38. }
  39. }
  40. // Attention a echapper $fragment, binaire potentiellement gz
  41. return array(
  42. 'id_article' => intval($id_article),
  43. 'id_fragment' => intval($id_fragment),
  44. 'version_min' => intval($version_min),
  45. 'version_max' => intval($version_max),
  46. 'compress' => $compress,
  47. 'fragment' => $fragment);
  48. }
  49. // http://doc.spip.org/@envoi_replace_fragments
  50. function envoi_replace_fragments($replaces) {
  51. $desc = $GLOBALS['tables_auxiliaires']['spip_versions_fragments'];
  52. foreach($replaces as $r)
  53. sql_replace('spip_versions_fragments', $r, $desc);
  54. }
  55. // http://doc.spip.org/@envoi_delete_fragments
  56. function envoi_delete_fragments($id_article, $deletes) {
  57. if (count($deletes)) {
  58. sql_delete("spip_versions_fragments", "id_article=$id_article AND ((". join(") OR (", $deletes)."))");
  59. }
  60. }
  61. //
  62. // Ajouter les fragments de la derniere version (tableau associatif id_fragment => texte)
  63. //
  64. // http://doc.spip.org/@ajouter_fragments
  65. function ajouter_fragments($id_article, $id_version, $fragments) {
  66. global $agregation_versions;
  67. $replaces = array();
  68. foreach ($fragments as $id_fragment => $texte) {
  69. $nouveau = true;
  70. // Recuperer la version la plus recente
  71. $row = sql_fetsel("compress, fragment, version_min, version_max", "spip_versions_fragments", "id_article=$id_article AND id_fragment=$id_fragment AND version_min<=$id_version", "", "version_min DESC", "1");
  72. if ($row) {
  73. $fragment = $row['fragment'];
  74. $version_min = $row['version_min'];
  75. if ($row['compress'] > 0) $fragment = @gzuncompress($fragment);
  76. $fragment = unserialize($fragment);
  77. if (is_array($fragment)) {
  78. unset($fragment[$id_version]);
  79. // Si le fragment n'est pas trop gros, prolonger celui-ci
  80. $nouveau = count($fragment) >= $agregation_versions
  81. && strlen($row['fragment']) > 1000;
  82. }
  83. }
  84. if ($nouveau) {
  85. $fragment = array($id_version => $texte);
  86. $version_min = $id_version;
  87. }
  88. else {
  89. // Ne pas dupliquer les fragments non modifies
  90. $modif = true;
  91. for ($i = $id_version - 1; $i >= $version_min; $i--) {
  92. if (isset($fragment[$i])) {
  93. $modif = ($fragment[$i] != $texte);
  94. break;
  95. }
  96. }
  97. if ($modif) $fragment[$id_version] = $texte;
  98. }
  99. // Preparer l'enregistrement du fragment
  100. $replaces[] = replace_fragment($id_article, $version_min, $id_version, $id_fragment, $fragment);
  101. }
  102. envoi_replace_fragments($replaces);
  103. }
  104. //
  105. // Supprimer tous les fragments d'un article lies a un intervalle de versions
  106. // (essaie d'eviter une trop grande fragmentation)
  107. //
  108. // http://doc.spip.org/@supprimer_fragments
  109. function supprimer_fragments($id_article, $version_debut, $version_fin) {
  110. global $agregation_versions;
  111. $replaces = array();
  112. $deletes = array();
  113. // D'abord, vider les fragments inutiles
  114. sql_delete("spip_versions_fragments", "id_article=$id_article AND version_min>=$version_debut AND version_max<=$version_fin");
  115. // Fragments chevauchant l'ensemble de l'intervalle, s'ils existent
  116. $result = sql_select("id_fragment, compress, fragment, version_min, version_max", "spip_versions_fragments", "id_article=$id_article AND version_min<$version_debut AND version_max>$version_fin");
  117. while ($row = sql_fetch($result)) {
  118. $id_fragment = $row['id_fragment'];
  119. $fragment = $row['fragment'];
  120. if ($row['compress'] > 0) $fragment = gzuncompress($fragment);
  121. $fragment = unserialize($fragment);
  122. for ($i = $version_fin; $i >= $version_debut; $i--) {
  123. if (isset($fragment[$i])) {
  124. // Recopier le dernier fragment si implicite
  125. if (!isset($fragment[$version_fin + 1]))
  126. $fragment[$version_fin + 1] = $fragment[$i];
  127. unset($fragment[$i]);
  128. }
  129. }
  130. $replaces[] = replace_fragment($id_article,
  131. $row['version_min'], $row['version_max'], $id_fragment, $fragment);
  132. }
  133. // Fragments chevauchant le debut de l'intervalle, s'ils existent
  134. $result = sql_select("id_fragment, compress, fragment, version_min, version_max", "spip_versions_fragments", "id_article=$id_article AND version_min<$version_debut AND version_max>=$version_debut AND version_max<=$version_fin");
  135. $deb_fragment = array();
  136. while ($row = sql_fetch($result)) {
  137. $id_fragment = $row['id_fragment'];
  138. $fragment = $row['fragment'];
  139. $version_min = $row['version_min'];
  140. $version_max = $row['version_max'];
  141. if ($row['compress'] > 0) $fragment = gzuncompress($fragment);
  142. $fragment = unserialize($fragment);
  143. for ($i = $version_debut; $i <= $version_max; $i++) {
  144. if (isset($fragment[$i])) unset($fragment[$i]);
  145. }
  146. // Stocker temporairement le fragment pour agregation
  147. $deb_fragment[$id_fragment] = $fragment;
  148. // Ajuster l'intervalle des versions
  149. $deb_version_min[$id_fragment] = $version_min;
  150. $deb_version_max[$id_fragment] = $version_debut - 1;
  151. }
  152. // Fragments chevauchant la fin de l'intervalle, s'ils existent
  153. $result = sql_select("id_fragment, compress, fragment, version_min, version_max", "spip_versions_fragments", "id_article=$id_article AND version_max>$version_fin AND version_min>=$version_debut AND version_min<=$version_fin");
  154. while ($row = sql_fetch($result)) {
  155. $id_fragment = $row['id_fragment'];
  156. $fragment = $row['fragment'];
  157. $version_min = $row['version_min'];
  158. $version_max = $row['version_max'];
  159. if ($row['compress'] > 0) $fragment = gzuncompress($fragment);
  160. $fragment = unserialize($fragment);
  161. for ($i = $version_fin; $i >= $version_min; $i--) {
  162. if (isset($fragment[$i])) {
  163. // Recopier le dernier fragment si implicite
  164. if (!isset($fragment[$version_fin + 1]))
  165. $fragment[$version_fin + 1] = $fragment[$i];
  166. unset($fragment[$i]);
  167. }
  168. }
  169. // Virer l'ancien enregistrement (la cle primaire va changer)
  170. $deletes[] = "id_fragment=$id_fragment AND version_min=$version_min";
  171. // Essayer l'agregation
  172. $agreger = false;
  173. if (isset($deb_fragment[$id_fragment])) {
  174. $agreger = (count($deb_fragment[$id_fragment]) + count($fragment) <= $agregation_versions);
  175. if ($agreger) {
  176. $fragment = $deb_fragment[$id_fragment] + $fragment;
  177. $version_min = $deb_version_min[$id_fragment];
  178. }
  179. else {
  180. $replaces[] = replace_fragment($id_article,
  181. $deb_version_min[$id_fragment], $deb_version_max[$id_fragment],
  182. $id_fragment, $deb_fragment[$id_fragment]);
  183. }
  184. unset($deb_fragment[$id_fragment]);
  185. }
  186. if (!$agreger) {
  187. // Ajuster l'intervalle des versions
  188. $version_min = $version_fin + 1;
  189. }
  190. $replaces[] = replace_fragment($id_article, $version_min, $version_max, $id_fragment, $fragment);
  191. }
  192. // Ajouter fragments restants
  193. if (is_array($deb_fragment) && count($deb_fragment) > 0) {
  194. foreach ($deb_fragment as $id_fragment => $fragment) {
  195. $replaces[] = replace_fragment($id_article,
  196. $deb_version_min[$id_fragment], $deb_version_max[$id_fragment],
  197. $id_fragment, $deb_fragment[$id_fragment]);
  198. }
  199. }
  200. envoi_replace_fragments($replaces);
  201. envoi_delete_fragments($id_article, $deletes);
  202. }
  203. //
  204. // Recuperer les fragments d'une version donnee
  205. // renvoie un tableau associatif (id_fragment => texte)
  206. //
  207. // http://doc.spip.org/@recuperer_fragments
  208. function recuperer_fragments($id_article, $id_version) {
  209. $fragments = array();
  210. if ($id_version == 0) return array();
  211. $result = sql_select("id_fragment, version_min, version_max, compress, fragment", "spip_versions_fragments", "id_article=$id_article AND version_min<=$id_version AND version_max>=$id_version");
  212. while ($row = sql_fetch($result)) {
  213. $id_fragment = $row['id_fragment'];
  214. $version_min = $row['version_min'];
  215. $fragment = $row['fragment'];
  216. if ($row['compress'] > 0){
  217. $fragment_ = @gzuncompress($fragment);
  218. if (strlen($fragment) && $fragment_===false)
  219. $fragment=serialize(array($row['version_max']=>"["._T('forum_titre_erreur').$id_fragment."]"));
  220. else
  221. $fragment = $fragment_;
  222. }
  223. $fragment_ = unserialize($fragment);
  224. if (strlen($fragment) && $fragment_===false)
  225. $fragment=array($row['version_max']=>"["._T('forum_titre_erreur').$id_fragment."]");
  226. else
  227. $fragment = $fragment_;
  228. for ($i = $id_version; $i >= $version_min; $i--) {
  229. if (isset($fragment[$i])) {
  230. ## hack destine a sauver les archives des sites iso-8859-1
  231. ## convertis en utf-8 (les archives ne sont pas converties
  232. ## mais ce code va les nettoyer ; pour les autres charsets
  233. ## la situation n'est pas meilleure ni pire qu'avant)
  234. if ($GLOBALS['meta']['charset'] == 'utf-8'
  235. AND include_spip('inc/charsets')
  236. AND !is_utf8($fragment[$i])) {
  237. $fragment[$i] = importer_charset($fragment[$i], 'iso-8859-1');
  238. }
  239. $fragments[$id_fragment] = $fragment[$i];
  240. break;
  241. }
  242. }
  243. }
  244. return $fragments;
  245. }
  246. //
  247. // Apparier des paragraphes deux a deux entre une version originale
  248. // et une version modifiee
  249. //
  250. // http://doc.spip.org/@apparier_paras
  251. function apparier_paras($src, $dest, $flou = true) {
  252. $src_dest = array();
  253. $dest_src = array();
  254. $t1 = $t2 = array();
  255. $md1 = $md2 = array();
  256. $gz_min1 = $gz_min2 = array();
  257. $gz_trans1 = $gz_trans2 = array();
  258. $l1 = $l2 = array();
  259. // Nettoyage de la ponctuation pour faciliter l'appariement
  260. foreach($src as $key => $val) {
  261. $t1[$key] = strval(preg_replace("/[[:punct:][:space:]]+/", " ", $val));
  262. }
  263. foreach($dest as $key => $val) {
  264. $t2[$key] = strval(preg_replace("/[[:punct:][:space:]]+/", " ", $val));
  265. }
  266. // Premiere passe : chercher les correspondance exactes
  267. foreach($t1 as $key => $val) $md1[$key] = md5($val);
  268. foreach($t2 as $key => $val) $md2[md5($val)][$key] = $key;
  269. foreach($md1 as $key1 => $h) {
  270. if (isset($md2[$h])) {
  271. $key2 = reset($md2[$h]);
  272. if ($t1[$key1] == $t2[$key2]) {
  273. $src_dest[$key1] = $key2;
  274. $dest_src[$key2] = $key1;
  275. unset($t1[$key1]);
  276. unset($t2[$key2]);
  277. unset($md2[$h][$key2]);
  278. }
  279. }
  280. }
  281. if ($flou) {
  282. // Deuxieme passe : recherche de correlation par test de compressibilite
  283. foreach($t1 as $key => $val) {
  284. $l1[$key] = strlen(gzcompress($val));
  285. }
  286. foreach($t2 as $key => $val) {
  287. $l2[$key] = strlen(gzcompress($val));
  288. }
  289. foreach($t1 as $key1 => $s1) {
  290. foreach($t2 as $key2 => $s2) {
  291. $r = strlen(gzcompress($s1.$s2));
  292. $taux = 1.0 * $r / ($l1[$key1] + $l2[$key2]);
  293. if (!$gz_min1[$key1] || $gz_min1[$key1] > $taux) {
  294. $gz_min1[$key1] = $taux;
  295. $gz_trans1[$key1] = $key2;
  296. }
  297. if (!$gz_min2[$key2] || $gz_min2[$key2] > $taux) {
  298. $gz_min2[$key2] = $taux;
  299. $gz_trans2[$key2] = $key1;
  300. }
  301. }
  302. }
  303. // Depouiller les resultats de la deuxieme passe :
  304. // ne retenir que les correlations reciproques
  305. foreach($gz_trans1 as $key1 => $key2) {
  306. if ($gz_trans2[$key2] == $key1 && $gz_min1[$key1] < 0.9) {
  307. $src_dest[$key1] = $key2;
  308. $dest_src[$key2] = $key1;
  309. }
  310. }
  311. }
  312. // Retourner les mappings
  313. return array($src_dest, $dest_src);
  314. }
  315. //
  316. // Recuperer les champs d'une version donnee
  317. //
  318. // http://doc.spip.org/@recuperer_version
  319. function recuperer_version($id_article, $id_version) {
  320. $champs = sql_getfetsel("champs", "spip_versions", "id_article=" . intval($id_article) . " AND id_version=" . intval($id_version));
  321. if (!$champs OR !is_array($champs = unserialize($champs)))
  322. return array();
  323. else return reconstuire_version($champs,
  324. recuperer_fragments($id_article, $id_version));
  325. }
  326. // http://doc.spip.org/@reconstuire_version
  327. function reconstuire_version($champs, $fragments, $res=array()) {
  328. static $msg;
  329. if (!$msg) $msg = _T('forum_titre_erreur');
  330. foreach ($champs as $nom => $code) {
  331. if (!isset($res[$nom])) {
  332. $t = '';
  333. foreach (array_filter(explode(' ', $code)) as $id) {
  334. $t .= isset($fragments[$id])
  335. ? $fragments[$id]
  336. : "[$msg$id]";
  337. }
  338. $res[$nom] = $t;
  339. }
  340. }
  341. return $res;
  342. }
  343. // http://doc.spip.org/@supprimer_versions
  344. function supprimer_versions($id_article, $version_min, $version_max) {
  345. sql_delete("spip_versions", "id_article=$id_article AND id_version>=$version_min AND id_version<=$version_max");
  346. supprimer_fragments($id_article, $version_min, $version_max);
  347. }
  348. //
  349. // Ajouter une version a un article
  350. //
  351. // http://doc.spip.org/@ajouter_version
  352. function ajouter_version($id_article, $champs, $titre_version = "", $id_auteur) {
  353. $paras = $paras_old = $paras_champ = $fragments = array();
  354. // Attention a une edition anonyme (type wiki): id_auteur n'est pas
  355. // definie, on enregistre alors le numero IP
  356. $str_auteur = intval($id_auteur) ? intval($id_auteur) : $GLOBALS['ip'];
  357. $permanent = empty($titre_version) ? 'non' : 'oui';
  358. // Detruire les tentatives d'archivages non abouties en 1 heure
  359. sql_delete('spip_versions', "id_article=$id_article AND id_version <= 0 AND date < DATE_SUB(".sql_quote(date('Y-m-d H:i:s')).", INTERVAL "._INTERVALLE_REVISIONS." SECOND)");
  360. // Signaler qu'on opere en mettant un numero de version negatif
  361. // distinctif (pour eviter la violation d'unicite)
  362. // et un titre contenant en fait le moment de l'insertion
  363. list($ms, $sec) = explode(' ', microtime());
  364. $date = $sec . substr($ms,1,4); // SQL ne ramene que 4 chiffres significatifs apres la virgule pour 0.0+titre_version
  365. $datediff = ($sec - mktime(0,0,0,9,1,2007)) * 1000000 + substr($ms,2, strlen($ms)-4);
  366. $valeurs = array('id_article' => $id_article,
  367. 'id_version' => (0 - $datediff),
  368. 'date' => date('Y-m-d H:i:s'),
  369. 'id_auteur' => $str_auteur, // varchar ici!
  370. 'titre_version' => $date);
  371. sql_insertq('spip_versions', $valeurs);
  372. // Eviter les validations entremelees en s'endormant s'il existe
  373. // une version <0 plus recente mais pas plus vieille que 10s
  374. // Une <0 encore plus vieille est une operation avortee,
  375. // on passe outre (vaut mieux archiver mal que pas du tout).
  376. // Pour tester:
  377. // 0. mettre le delai a 30
  378. // 1. decommenter le premier sleep(15)
  379. // 2. enregistrer une modif
  380. // 3. recommenter le premier sleep(15), decommenter le second.
  381. // 4. enregistrer une autre modif dans les 15 secondes
  382. # sleep(15);
  383. $delai = $sec-10;
  384. while (sql_countsel('spip_versions', "id_article=$id_article AND id_version < 0 AND 0.0+titre_version < $date AND 0.0+titre_version > $delai")) {
  385. spip_log("version $id_article :insertion en cours avant $date ($delai)");
  386. sleep(1);
  387. $delai++;
  388. }
  389. # sleep(15); spip_log("sortie $sec $delai");
  390. // Determiner le numero du prochain fragment
  391. $next = sql_fetsel("id_fragment", "spip_versions_fragments", "id_article=$id_article", "", "id_fragment DESC", "1");
  392. $onlylock = '';
  393. // Examiner la derniere version
  394. $row = sql_fetsel("id_version, champs, id_auteur, date, permanent", "spip_versions", "id_article=$id_article AND id_version > 0", '', "id_version DESC", "1"); // le champ id_auteur est un varchar dans cette table
  395. if ($row) {
  396. $id_version = $row['id_version'];
  397. $paras_old = recuperer_fragments($id_article, $id_version);
  398. $champs_old = $row['champs'];
  399. if ($row['id_auteur']!= $str_auteur
  400. OR $row['permanent']=='oui'
  401. OR strtotime($row['date']) < (time()-_INTERVALLE_REVISIONS)) {
  402. $id_version++;
  403. // version precedente recente, on va la mettre a jour
  404. // avec les nouveaux arrivants si presents
  405. } else {
  406. $champs = reconstuire_version(unserialize($champs_old), $paras_old, $champs);
  407. $onlylock = 're';
  408. }
  409. } else $id_version = 1;
  410. $next = !$next ? 1 : ($next['id_fragment'] + 1);
  411. // Generer les nouveaux fragments
  412. $codes = array();
  413. foreach ($champs as $nom => $texte) {
  414. $codes[$nom] = array();
  415. $paras = separer_paras($texte, $paras);
  416. $paras_champ[$nom] = count($paras);
  417. }
  418. // Apparier les fragments de maniere optimale
  419. $n = count($paras);
  420. if ($n) {
  421. // Tables d'appariement dans les deux sens
  422. list(,$trans) = apparier_paras($paras_old, $paras);
  423. reset($champs);
  424. $nom = '';
  425. for ($i = 0; $i < $n; $i++) {
  426. while ($i >= $paras_champ[$nom]) list($nom, ) = each($champs);
  427. // Lier au fragment existant si possible, sinon creer un nouveau fragment
  428. $id_fragment = isset($trans[$i]) ? $trans[$i] : $next++;
  429. $codes[$nom][] = $id_fragment;
  430. $fragments[$id_fragment] = $paras[$i];
  431. }
  432. }
  433. foreach ($champs as $nom => $t) {
  434. $codes[$nom] = join(' ', $codes[$nom]);
  435. # avec la ligne qui suit, un champ qu'on vide ne s'enregistre pas
  436. # if (!strlen($codes[$nom])) unset($codes[$nom]);
  437. }
  438. // Enregistrer les modifications
  439. ajouter_fragments($id_article, $id_version, $fragments);
  440. sql_updateq("spip_articles", array("id_version" => $id_version), "id_article=$id_article");
  441. // Si l'insertion ne servait que de verrou,
  442. // la detruire apres mise a jour de l'ancienne entree,
  443. // sinon la mise a jour efface en fait le verrou.
  444. if (!$onlylock) {
  445. sql_updateq('spip_versions', array('id_version'=>$id_version, 'date'=>date('Y-m-d H:i:s'), 'champs'=> serialize($codes), 'permanent'=>$permanent, 'titre_version'=> $titre_version), "id_article=$id_article AND id_version < 0 AND titre_version='$date'");
  446. } else {
  447. sql_updateq('spip_versions', array('date'=>date('Y-m-d H:i:s'), 'champs'=>serialize($codes), 'permanent'=>$permanent, 'titre_version'=> $titre_version), "id_article=$id_article AND id_version=$id_version");
  448. sql_delete("spip_versions", "id_article=$id_article AND id_version < 0 AND titre_version ='$date'");
  449. }
  450. spip_log($onlylock . "memorise la version $id_version de l'article $id_article $titre_version");
  451. return $id_version;
  452. }
  453. // les textes "diff" ne peuvent pas passer dans propre directement,
  454. // car ils contiennent des <span> et <div> parfois mal places
  455. // http://doc.spip.org/@propre_diff
  456. function propre_diff($texte) {
  457. $span_diff = array();
  458. if (preg_match_all(',<(/)?(span|div) (class|rem)="diff-[^>]*>,', $texte, $regs, PREG_SET_ORDER)) {
  459. foreach ($regs as $c => $reg) {
  460. $texte = str_replace($reg[0], '@@@SPIP_DIFF'.$c.'@@@', $texte);
  461. }
  462. }
  463. // [ ...<span diff> -> lien ]
  464. // < tag <span diff> >
  465. $texte = preg_replace(',<([^>]*?@@@SPIP_DIFF[0-9]+@@@),',
  466. '&lt;\1', $texte);
  467. # attention ici astuce seulement deux @@ finals car on doit eviter
  468. # deux patterns a suivre, afin de pouvoir prendre [ mais eviter [[
  469. $texte = preg_replace(',(^|[^[])[[]([^[\]]*@@@SPIP_DIFF[0-9]+@@),',
  470. '\1&#91;\2', $texte);
  471. // desactiver TeX & toujours-paragrapher
  472. $tex = $GLOBALS['traiter_math'];
  473. $GLOBALS['traiter_math'] = '';
  474. $mem = $GLOBALS['toujours_paragrapher'];
  475. $GLOBALS['toujours_paragrapher'] = false;
  476. $texte = propre($texte);
  477. // retablir
  478. $GLOBALS['traiter_math'] = $tex;
  479. $GLOBALS['toujours_paragrapher'] = $mem;
  480. // un blockquote mal ferme peut gener l'affichage, et title plante safari
  481. $texte = preg_replace(',<(/?(blockquote|title)[^>]*)>,i', '&lt;\1>', $texte);
  482. // Dans les <cadre> c'est un peu plus complique
  483. if (preg_match_all(',<textarea (.*)</textarea>,Uims', $texte, $area, PREG_SET_ORDER)) {
  484. foreach ($area as $reg) {
  485. $remplace = preg_replace(',@@@SPIP_DIFF[0-9]+@@@,', '**', $reg[0]);
  486. if ($remplace <> $reg[0])
  487. $texte = str_replace($reg[0], $remplace, $texte);
  488. }
  489. }
  490. // replacer les valeurs des <span> et <div> diff-
  491. if (is_array($regs))
  492. foreach ($regs as $c => $reg) {
  493. $bal = (!$reg[1]) ? $reg[0] : "</$reg[2]>";
  494. $texte = str_replace('@@@SPIP_DIFF'.$c.'@@@', $bal, $texte);
  495. $GLOBALS['les_notes'] = str_replace('@@@SPIP_DIFF'.$c.'@@@', $bal, $GLOBALS['les_notes']);
  496. }
  497. // quand le dernier tag est ouvrant le refermer ...
  498. $reg = end($regs);
  499. if (!$reg[1] AND $reg[2]) $texte.="</$reg[2]>";
  500. return $texte;
  501. }
  502. // liste les champs versionnes d'un objet
  503. // http://doc.spip.org/@liste_champs_versionnes
  504. function liste_champs_versionnes($table) {
  505. $champs = array();
  506. switch ($table) {
  507. case 'spip_articles':
  508. $champs += array('id_rubrique', 'surtitre', 'titre', 'soustitre', 'j_mots', 'descriptif', 'nom_site', 'url_site', 'chapo', 'texte', 'ps');
  509. // prendre en compte les champs extras2
  510. if (function_exists($f = 'cextras_get_extras_match')
  511. AND is_array($g = $f($table)))
  512. foreach($g as $c)
  513. $champs[] = $c->champ;
  514. break;
  515. # case 'spip_rubriques':
  516. # $champs += array('titre', 'descriptif', 'texte');
  517. # break;
  518. default:
  519. break;
  520. }
  521. return $champs;
  522. }
  523. // http://doc.spip.org/@enregistrer_premiere_revision
  524. function enregistrer_premiere_revision($x) {
  525. if ($GLOBALS['meta']["articles_versions"]=='oui'
  526. AND $champs = liste_champs_versionnes($x['args']['table'])) {
  527. $id_article = $x['args']['id_objet'];
  528. if (!sql_countsel('spip_versions',"id_article=$id_article")) {
  529. $originaux = sql_fetsel("*", 'spip_articles', "id_article=$id_article");
  530. foreach($champs as $v)
  531. if (isset($originaux[$v]))
  532. $champs_originaux[$v] = $originaux[$v];
  533. // Si le titre est vide, c'est qu'on vient de creer l'article
  534. if ($champs_originaux['titre'] != '') {
  535. $date_modif = $champs_originaux['date_modif'];
  536. $date = $champs_originaux['date'];
  537. unset ($champs_originaux['date_modif']);
  538. unset ($champs_originaux['date']);
  539. $id_version = ajouter_version($id_article, $champs_originaux, _T('version_initiale'), 0);
  540. // Inventer une date raisonnable pour la version initiale
  541. if ($date_modif>'1970-')
  542. $date_modif = strtotime($date_modif);
  543. else if ($date>'1970-')
  544. $date_modif = strtotime($date);
  545. else
  546. $date_modif = time()-7200;
  547. sql_updateq('spip_versions', array('date' => date("Y-m-d H:i:s", $date_modif)), "id_article=$id_article AND id_version=$id_version");
  548. }
  549. }
  550. }
  551. return $x;
  552. }
  553. // http://doc.spip.org/@enregistrer_nouvelle_revision
  554. function enregistrer_nouvelle_revision($x) {
  555. if ($GLOBALS['meta']["articles_versions"] != 'oui')
  556. return $x;
  557. // Regarder si au moins une des modifs est versionnable
  558. $champs = array();
  559. foreach (liste_champs_versionnes($x['args']['table']) as $key)
  560. if (isset($x['data'][$key]))
  561. $champs[$key] = $x['data'][$key];
  562. // A moins qu'il ne s'agisse d'operation (ajout/suppr) sur les mots-cles?
  563. if ($x['args']['operation'] == 'editer_mots'
  564. AND $x['args']['table'] == 'spip_articles') {
  565. include_spip('inc/texte');
  566. $mots = array();
  567. foreach(
  568. sql_allfetsel('id_mot', 'spip_mots_articles',
  569. 'id_article='.sql_quote($x['args']['id_objet']))
  570. as $mot)
  571. $mots[] = "[->mot".$mot['id_mot']."]";
  572. $champs['j_mots'] = join(' ', $mots);
  573. }
  574. if (count($champs))
  575. ajouter_version($x['args']['id_objet'], $champs, '', $GLOBALS['visiteur_session']['id_auteur']);
  576. return $x;
  577. }
  578. ?>