diff --git a/.gitattributes b/.gitattributes index 8c3b2d04f1dbd923dc34ac6cb47d18776aa72ba9..4258e61787919b1b50a56c3fa3d82fc1964829ca 100644 --- a/.gitattributes +++ b/.gitattributes @@ -128,6 +128,7 @@ ecrire/img_pack/forum-droite_rtl.gif -text ecrire/img_pack/forum-interne-24.gif -text ecrire/img_pack/forum-vert.gif -text ecrire/img_pack/groupe-mot-24.gif -text +ecrire/img_pack/historique-24.gif -text ecrire/img_pack/image-24.gif -text ecrire/img_pack/interface-display.gif -text ecrire/img_pack/jauge-fond.gif -text diff --git a/ecrire/articles.php3 b/ecrire/articles.php3 index 5f28804394846a0f1892a363a4cb92f8187ee4de..27a520dded048bd5eaf4165870ebc02d4e5a32f9 100644 --- a/ecrire/articles.php3 +++ b/ecrire/articles.php3 @@ -232,16 +232,12 @@ if ($changer_virtuel && $flag_editable) { } if ($titre && !$ajout_forum && $flag_editable) { - $surtitre = addslashes(corriger_caracteres($surtitre)); - $titre = addslashes(corriger_caracteres($titre)); - $soustitre = addslashes(corriger_caracteres($soustitre)); - $descriptif = addslashes(corriger_caracteres($descriptif)); - $nom_site = addslashes(corriger_caracteres($nom_site)); - $url_site = addslashes(corriger_caracteres($url_site)); - $chapo = addslashes(corriger_caracteres($chapo)); - $texte = addslashes(corriger_caracteres($texte)); - $ps = addslashes(corriger_caracteres($ps)); - + $champs = array('surtitre', 'titre', 'soustitre', 'descriptif', 'nom_site', 'url_site', 'chapo', 'texte', 'ps'); + $champs_version = array(); + foreach ($champs as $nom_champ) { + $t = $champs_versions[$nom_champ] = corriger_caracteres($$nom_champ); + $$nom_champ = addslashes($t); + } // recoller les champs du extra if ($champs_extra) { @@ -266,7 +262,7 @@ if ($titre && !$ajout_forum && $flag_editable) { // Stockage des versions if ($articles_versions != 'non') { include_ecrire("inc_diff.php3"); - ajouter_version($id_article, stripslashes($chapo), stripslashes($texte), stripslashes($ps), ''); + ajouter_version($id_article, $champs_versions); } // Changer la langue heritee @@ -338,6 +334,7 @@ if ($row = spip_fetch_array($result)) { $referers = $row["referers"]; $extra = $row["extra"]; $id_trad = $row["id_trad"]; + $id_version = $row["id_version"]; } // pour l'affichage du virtuel @@ -422,6 +419,10 @@ if ($connect_statut == "0minirezo" AND $statut_article == 'publie' AND $visites icone_horizontale(_T('icone_evolution_visites', array('visites' => $visites)), "statistiques_visites.php3?id_article=$id_article", "statistiques-24.gif","rien.gif"); } +if ($articles_versions != 'non' AND $connect_statut == "0minirezo" AND $id_version>1) { + icone_horizontale(_L('Afficher les révisions...'), "articles_versions.php3?id_article=$id_article", "historique-24.gif", "rien.gif"); +} + echo "</div>\n"; fin_boite_info(); diff --git a/ecrire/articles_versions.php3 b/ecrire/articles_versions.php3 index 41667595a5f97d956a9b4810d2729bdc806ad8cc..46cde1218aa6e84226bfa14c9c339b738cef6909 100644 --- a/ecrire/articles_versions.php3 +++ b/ecrire/articles_versions.php3 @@ -1,68 +1,23 @@ <?php -include ("inc.php3"); +include("inc.php3"); -include_ecrire ("inc_diff.php3"); +include_ecrire("inc_diff.php3"); -$articles_surtitre = lire_meta("articles_surtitre"); -$articles_soustitre = lire_meta("articles_soustitre"); -$articles_descriptif = lire_meta("articles_descriptif"); -$articles_urlref = lire_meta("articles_urlref"); -$articles_chapeau = lire_meta("articles_chapeau"); -$articles_ps = lire_meta("articles_ps"); -$articles_redac = lire_meta("articles_redac"); -$articles_mots = lire_meta("articles_mots"); -$articles_versions = lire_meta("articles_versions"); - -$clean_link = new Link("articles.php3?id_article=$id_article"); - -// Initialiser doublons pour documents (completes par "propre($texte)") -$id_doublons['documents'] = "0"; - - - -////////////////////////////////////////////////////// -// Determiner les droits d'edition de l'article -// - -$query = "SELECT statut, titre, id_rubrique FROM spip_articles WHERE id_article=$id_article"; -$result = spip_query($query); -if ($row = spip_fetch_array($result)) { - $statut_article = $row['statut']; - $titre_article = $row['titre']; - $rubrique_article = $row['id_rubrique']; -} -else { - $statut_article = ''; -} - -$query = "SELECT * FROM spip_auteurs_articles WHERE id_article=$id_article AND id_auteur=$connect_id_auteur"; -$result_auteur = spip_query($query); - -$flag_auteur = (spip_num_rows($result_auteur) > 0); -$flag_editable = (acces_rubrique($rubrique_article) - OR ($flag_auteur AND ($statut_article == 'prepa' OR $statut_article == 'prop' OR $statut_article == 'poubelle'))); // // Lire l'article // +$champs = array('surtitre', 'titre', 'soustitre', 'descriptif', 'nom_site', 'url_site', 'chapo', 'texte', 'ps'); + $query = "SELECT * FROM spip_articles WHERE id_article='$id_article'"; $result = spip_query($query); if ($row = spip_fetch_array($result)) { $id_article = $row["id_article"]; - $surtitre = $row["surtitre"]; - $titre = $row["titre"]; - $soustitre = $row["soustitre"]; $id_rubrique = $row["id_rubrique"]; - $descriptif = $row["descriptif"]; - $nom_site = $row["nom_site"]; - $url_site = $row["url_site"]; - $chapo = $row["chapo"]; - $texte = $row["texte"]; - $ps = $row["ps"]; $date = $row["date"]; $statut_article = $row["statut"]; $maj = $row["maj"]; @@ -73,19 +28,54 @@ if ($row = spip_fetch_array($result)) { $id_trad = $row["id_trad"]; } -if (ereg("([0-9]{4})-([0-9]{2})-([0-9]{2})", $date_redac, $regs)) { - $mois_redac = $regs[2]; - $jour_redac = $regs[3]; - $annee_redac = $regs[1]; - if ($annee_redac > 4000) $annee_redac -= 9000; +if (!($id_version = intval($id_version))) { + $id_version = intval($row['id_version']); } +$textes = recuperer_version($id_article, $id_version); + +$id_diff = intval($id_diff); +if (!$id_diff) { + $diff_auto = true; + $query = "SELECT id_version FROM spip_versions WHERE id_article=$id_article ". + "AND id_version<$id_version ORDER BY id_version DESC LIMIT 0,1"; + if ($result = spip_query($query)) { + $row = mysql_fetch_array($result); + $id_diff = $row['id_version']; + } +} + +// +// Calculer le diff +// + +if ($id_version && $id_diff) { + include_ecrire("inc_difflcs.php3"); + + if ($id_diff > $id_version) { + $t = $id_version; + $id_version = $id_diff; + $id_diff = $t; + $old = $textes; + $new = $textes = recuperer_version($id_article, $id_version); + } + else { + $old = recuperer_version($id_article, $id_diff); + $new = $textes; + } + + $textes = array(); + + foreach ($champs as $champ) { + if (!$new[$champ] && !$old[$champ]) continue; -if (ereg("([0-9]{4})-([0-9]{2})-([0-9]{2})", $date, $regs)) { - $mois = $regs[2]; - $jour = $regs[3]; - $annee = $regs[1]; + $diff = new Diff(new DiffTexte); + $textes[$champ] = afficher_diff($diff->comparer(preparer_diff($new[$champ]), preparer_diff($old[$champ]))); + } } +if (is_array($textes)) +foreach ($textes as $var => $t) $$var = $t; + debut_page("« $titre_article »", "documents", "articles"); @@ -93,7 +83,7 @@ debut_page("« $titre_article »", "documents", "articles"); debut_grand_cadre(); afficher_parents($id_rubrique); -$parents="~ <img src='img_pack/racine-site-24.gif' width=24 height=24 align='middle'> <A HREF='naviguer.php3?coll=0'><B>"._T('lien_racine_site')."</B></A> ".aide ("rubhier")."<BR>".$parents; +$parents="~ <img src='img_pack/racine-site-24.gif' width=24 height=24 align='middle' alt='' /> <a href='naviguer.php3?coll=0'><b> "._T('lien_racine_site')."</b> </a> ".aide ("rubhier")."<br /> ".$parents; $parents=ereg_replace("~"," ",$parents); $parents=ereg_replace(" ","",$parents); echo "$parents"; @@ -116,10 +106,9 @@ debut_gauche(); debut_droite(); - changer_typo('','article'.$id_article); - +echo "<a name='diff'></a>\n"; debut_cadre_relief(); @@ -144,17 +133,17 @@ else if ($statut_article == 'poubelle') { } -echo "\n<table cellpadding=0 cellspacing=0 border=0 width='100%'>"; +echo "\n<table cellpadding='0' cellspacing='0' border='0' width='100%'>"; echo "<tr width='100%'><td width='100%' valign='top'>"; if ($surtitre) { - echo "<span $dir_lang><font face='arial,helvetica' size=3><b>"; + echo "<span $dir_lang><font face='arial,helvetica' size='3'><b>"; echo typo($surtitre); echo "</b></font></span>\n"; } - gros_titre($titre, $logo_statut); +gros_titre($titre, $logo_statut); if ($soustitre) { - echo "<span $dir_lang><font face='arial,helvetica' size=3><b>"; + echo "<span $dir_lang><font face='arial,helvetica' size='3'><b>"; echo typo($soustitre); echo "</b></font></span>\n"; } @@ -162,14 +151,21 @@ if ($soustitre) { if ($descriptif OR $url_site OR $nom_site) { echo "<p><div align='left' style='padding: 5px; border: 1px dashed #aaaaaa; background-color: #e4e4e4;' $dir_lang>"; - echo "<font size=2 face='Verdana,Arial,Sans,sans-serif'>"; + echo "<font size='2' face='Verdana,Arial,Sans,sans-serif'>"; $texte_case = ($descriptif) ? "{{"._T('info_descriptif')."}} $descriptif\n\n" : ''; $texte_case .= ($nom_site.$url_site) ? "{{"._T('info_urlref')."}} [".$nom_site."->".$url_site."]" : ''; echo propre($texte_case); echo "</font>"; echo "</div>"; } -echo "</td></tr></table>"; + +echo "</td>"; + +echo "<td align='center'>"; +icone(_L("Retour à l'article"), "articles.php3?id_article=$id_article", "", "article-24.gif"); +echo "</td>"; + +echo "</tr></table>"; ////////////////////////////////////////////////////// @@ -179,23 +175,40 @@ echo "</td></tr></table>"; debut_cadre_relief(); $query = "SELECT id_version, date, v.id_auteur, a.nom FROM spip_versions AS v, spip_auteurs AS a ". - "WHERE id_article=$id_article AND v.id_auteur=a.id_auteur ORDER BY date"; + "WHERE id_article=$id_article AND v.id_auteur=a.id_auteur ORDER BY date DESC"; $result = spip_query($query); -echo "<ul>"; +echo "<ul class='verdana3'>"; while ($row = spip_fetch_array($result)) { echo "<li>\n"; $date = affdate_heure($row['date']); - if ($row['id_version'] != $id_version) { + $version_aff = $row['id_version']; + if ($version_aff != $id_version) { $link = new Link(); - $link->addVar('id_version', $row['id_version']); - echo "<a href='".$link->getUrl()."'>$date</a>"; + $link->addVar('id_version', $version_aff); + $link->delVar('id_diff'); + echo "<a href='".$link->getUrl('diff')."' title=\"Afficher cette version\">$date</a>"; } else { echo "<b>$date</b>"; } echo " (".$row['nom'].")"; - echo " <span style='color:#989898; font-size: 80%; font-weight: bold;'><i>#".$row['id_version']."</i></span>"; + if ($options == 'avancees') { + //echo " <span style='color:#989898; font-size: 80%; font-weight: bold;'><i>#".$row['id_version']."</i></span>"; + if ($version_aff != $id_version) { + echo " <span class='verdana2'>"; + if ($version_aff == $id_diff) { + echo "<b>(comparaison)</b>"; + } + else { + $link = new Link(); + $link->addVar('id_version', $id_version); + $link->addVar('id_diff', $version_aff); + echo "(<a href='".$link->getUrl('diff')."' title=\"Afficher les modifications d'avec cette version\">comparaison</a>)"; + } + echo "</span>"; + } + } echo "</li>\n"; } echo "</ul>\n"; @@ -210,11 +223,6 @@ fin_cadre_relief(); if ($id_version) { echo "\n\n<div align='justify'>"; - $champs = recuperer_version($id_article, $id_version); - $chapo = $champs['chapo']; - $texte = $champs['texte']; - $ps = $champs['ps']; - // pour l'affichage du virtuel unset($virtuel); if (substr($chapo, 0, 1) == '=') { @@ -238,7 +246,7 @@ if ($id_version) { if ($ps) { echo debut_cadre_enfonce(); - echo "<div $dir_lang><font size=2 face='Verdana,Arial,Sans,sans-serif'>"; + echo "<div $dir_lang><font size='2' face='Verdana,Arial,Sans,sans-serif'>"; echo justifier("<b>"._T('info_ps')."</b> ".propre($ps)); echo "</font></div>"; echo fin_cadre_enfonce(); @@ -247,7 +255,7 @@ if ($id_version) { if ($les_notes) { echo debut_cadre_relief(); - echo "<div $dir_lang><font size=2>"; + echo "<div $dir_lang><font size='2'>"; echo justifier("<b>"._T('info_notes')." :</b> ".$les_notes); echo "</font></div>"; echo fin_cadre_relief(); @@ -266,4 +274,3 @@ fin_cadre_relief(); fin_page(); ?> - diff --git a/ecrire/img_pack/historique-24.gif b/ecrire/img_pack/historique-24.gif new file mode 100644 index 0000000000000000000000000000000000000000..0d34cb6c76f2b620bf137b071e0f7226abb24151 Binary files /dev/null and b/ecrire/img_pack/historique-24.gif differ diff --git a/ecrire/inc_diff.php3 b/ecrire/inc_diff.php3 index 1e35a941d042d2117e1e1b58b31c61439c56d934..18ce8760a27a06177ed5c8554bf81fcf96438d21 100644 --- a/ecrire/inc_diff.php3 +++ b/ecrire/inc_diff.php3 @@ -6,7 +6,6 @@ if (defined("_ECRIRE_INC_DIFF")) return; define("_ECRIRE_INC_DIFF", "1"); - function separer_paras($texte, $paras = "") { if (!$paras) $paras = array(); while (preg_match("/(\r\n?){2,}|\n{2,}/", $texte, $regs)) { @@ -39,8 +38,8 @@ function ajouter_fragments($id_article, $id_version, $fragments) { $fragment = unserialize($fragment); if (is_array($fragment)) { unset($fragment[$id_version]); - // Si moins de cinq revisions distinctes dans le fragment, prolonger celui-ci - if (count($fragment) < 5) $nouveau = false; + // Si le fragment n'est pas trop gros, prolonger celui-ci + $nouveau = count($fragment) > 8 && strlen($row['fragment']) > 1000; } } if ($nouveau) { @@ -66,7 +65,7 @@ function ajouter_fragments($id_article, $id_version, $fragments) { if ($flag_gz) { $s = gzcompress($fragment); if (strlen($s) < strlen($fragment)) { - //echo "gain gz: ".(100 - 100 * strlen($s) / strlen($fragment))."%<br>"; + //echo "gain gz: ".(100 - 100 * strlen($s) / strlen($fragment))."%<br />"; $compress = 1; $fragment = $s; } @@ -88,6 +87,7 @@ function ajouter_fragments($id_article, $id_version, $fragments) { // renvoie un tableau associatif (id_fragment => texte) // function recuperer_fragments($id_article, $id_version) { + $id_version = intval($id_version); $fragments = array(); $query = "SELECT id_fragment, version_min, compress, fragment FROM spip_versions_fragments ". @@ -115,7 +115,7 @@ function recuperer_fragments($id_article, $id_version) { // Apparier des paragraphes deux a deux entre une version originale // et une version modifiee // -function apparier_paras($src, $dest) { +function apparier_paras($src, $dest, $flou = true) { $src_dest = array(); $dest_src = array(); @@ -134,67 +134,55 @@ function apparier_paras($src, $dest) { $t2[$key] = preg_replace("/[[:punct:][:space:]]+/", " ", $val); } - // Hash pour premiere passe - foreach($t1 as $key => $val) $md1[md5($val)] = $key; - foreach($t2 as $key => $val) $md2[md5($val)] = $key; - // Premiere passe : chercher les correspondance exactes - foreach($md1 as $h => $key1) { - if (isset($md2[$h])) { - $key2 = $md2[$h]; + foreach($t1 as $key => $val) $md1[$key] = md5($val); + foreach($t2 as $key => $val) $md2[md5($val)][$key] = $key; + foreach($md1 as $key1 => $h) { + if (count($md2[$h])) { + $key2 = reset($md2[$h]); if ($t1[$key1] == $t2[$key2]) { $src_dest[$key1] = $key2; $dest_src[$key2] = $key1; unset($t1[$key1]); unset($t2[$key2]); + unset($md2[$h][$key2]); } } } - // Deuxieme passe : recherche de correlation par test de compressibilite - foreach($t1 as $key => $val) { - $l1[$key] = strlen(gzcompress($val)); - } - foreach($t2 as $key => $val) { - $l2[$key] = strlen(gzcompress($val)); - } - foreach($t1 as $key1 => $s1) { - //echo "<br>"; - foreach($t2 as $key2 => $s2) { - $r = strlen(gzcompress($s1.$s2)); - //$k += strlen($s1) + strlen($s2); - $taux = 1.0 * $r / ($l1[$key1] + $l2[$key2]); - //echo "<li>$key1 => $key2 : $taux</li>"; - if (!$gz_min1[$key1] || $gz_min1[$key1] > $taux) { - $gz_min1[$key1] = $taux; - $gz_trans1[$key1] = $key2; - } - if (!$gz_min2[$key2] || $gz_min2[$key2] > $taux) { - $gz_min2[$key2] = $taux; - $gz_trans2[$key2] = $key1; + if ($flou) { + // Deuxieme passe : recherche de correlation par test de compressibilite + foreach($t1 as $key => $val) { + $l1[$key] = strlen(gzcompress($val)); + } + foreach($t2 as $key => $val) { + $l2[$key] = strlen(gzcompress($val)); + } + foreach($t1 as $key1 => $s1) { + foreach($t2 as $key2 => $s2) { + $r = strlen(gzcompress($s1.$s2)); + $taux = 1.0 * $r / ($l1[$key1] + $l2[$key2]); + if (!$gz_min1[$key1] || $gz_min1[$key1] > $taux) { + $gz_min1[$key1] = $taux; + $gz_trans1[$key1] = $key2; + } + if (!$gz_min2[$key2] || $gz_min2[$key2] > $taux) { + $gz_min2[$key2] = $taux; + $gz_trans2[$key2] = $key1; + } } } - } - //echo "$k octets compresses<p>"; - - // Depouiller les resultats de la deuxieme passe : - // ne retenir que les correlations reciproques - foreach($gz_trans1 as $key1 => $key2) { - if ($gz_trans2[$key2] == $key1 && $gz_min1[$key1] < 0.9) { - $src_dest[$key1] = $key2; - $dest_src[$key2] = $key1; + + // Depouiller les resultats de la deuxieme passe : + // ne retenir que les correlations reciproques + foreach($gz_trans1 as $key1 => $key2) { + if ($gz_trans2[$key2] == $key1 && $gz_min1[$key1] < 0.9) { + $src_dest[$key1] = $key2; + $dest_src[$key2] = $key1; + } } } - /*echo "<br>"; - foreach ($gz_trans1 as $a => $b) { - echo "$a => $b<br>"; - echo "<blockquote><div style='border: 1px solid black'>".$t1[$a]."</div>"; - echo "<div style='border: 1px solid black'>".$t2[$b]."</div></blockquote>"; - } - echo "<br>"; - foreach ($gz_trans2 as $b => $a) echo "$a $b<br>";*/ - // Retourner les mappings return array($src_dest, $dest_src); } @@ -204,23 +192,21 @@ function apparier_paras($src, $dest) { // Recuperer les champs d'une version donnee // function recuperer_version($id_article, $id_version) { - $query = "SELECT chapo, texte, ps, extra FROM spip_versions ". + if (!$id_version) $id_version = '0'; + $query = "SELECT champs FROM spip_versions ". "WHERE id_article=$id_article AND id_version=$id_version"; $result = spip_query($query); if (!($row = spip_fetch_array($result))) return false; - $codes['chapo'] = $row['chapo']; - $codes['texte'] = $row['texte']; - $codes['ps'] = $row['ps']; - $fragments = recuperer_fragments($id_article, $id_version); + $champs = unserialize($row['champs']); $textes = array(); - foreach ($codes as $var => $code) { - $textes[$var] = ""; + foreach ($champs as $nom_champ => $code) { + $textes[$nom_champ] = ""; $code = explode(' ', $code); foreach ($code as $id_fragment) { - $textes[$var] .= $fragments[$id_fragment]; + $textes[$nom_champ] .= $fragments[$id_fragment]; } } return $textes; @@ -229,15 +215,15 @@ function recuperer_version($id_article, $id_version) { // // Ajouter une version a un article // -function ajouter_version($id_article, $chapo, $texte, $ps, $extra) { +function ajouter_version($id_article, $champs) { global $connect_id_auteur; // Eviter les validations entremelees $lock = "ajout_version $id_article"; - spip_get_lock($lock, 5); + spip_get_lock($lock, 10); // Examiner la derniere version - $query = "SELECT id_version, (id_auteur=$connect_id_auteur AND date > DATE_SUB(NOW(), INTERVAL 1 HOUR) AND permanent!='oui') AS flag ". + $query = "SELECT id_version, (id_auteur=$connect_id_auteur AND date > DATE_SUB(NOW(), INTERVAL 1 SECOND) AND permanent!='oui') AS flag ". "FROM spip_versions WHERE id_article=$id_article ". "ORDER BY id_version DESC LIMIT 0,1"; $result = spip_query($query); @@ -262,46 +248,46 @@ function ajouter_version($id_article, $chapo, $texte, $ps, $extra) { // Generer les nouveaux fragments $fragments = array(); $paras_old = recuperer_fragments($id_article, $id_version); - $paras_new = $paras_var = array(); - $vars = array('chapo', 'texte', 'ps'); - foreach ($vars as $var) { - $codes[$var] = array(); - $paras_new = separer_paras($$var, $paras_new); - $paras_var[$var] = count($paras_new); + $paras_new = $paras_champ = array(); + foreach ($champs as $nom_champ => $texte) { + $codes[$nom_champ] = array(); + $paras_new = separer_paras($texte, $paras_new); + $paras_champ[$nom_champ] = count($paras_new); } // Apparier les fragments de maniere optimale $n = count($paras_new); if ($n) { + // Tables d'appariement dans les deux sens list($trans, $trans_rev) = apparier_paras($paras_old, $paras_new); - reset($vars); - $var = ''; + reset($champs); + $nom_champ = ''; for ($i = 0; $i < $n; $i++) { - while ($i >= $paras_var[$var]) list(, $var) = each($vars); + while ($i >= $paras_champ[$nom_champ]) list($nom_champ, ) = each($champs); // Lier au fragment existant si possible, sinon creer un nouveau fragment if (isset($trans_rev[$i])) $id_fragment = $trans_rev[$i]; else $id_fragment = $id_fragment_next++; - $codes[$var][] = $id_fragment; + $codes[$nom_champ][] = $id_fragment; $fragments[$id_fragment] = $paras_new[$i]; } } - foreach ($vars as $var) $codes[$var] = join(' ', $codes[$var]); + foreach ($champs as $nom_champ => $t) { + $codes[$nom_champ] = join(' ', $codes[$nom_champ]); + if (!strlen($codes[$nom_champ])) unset($codes[$nom_champ]); + } // Enregistrer les modifications ajouter_fragments($id_article, $id_version_new, $fragments); - $code_chapo = addslashes($codes['chapo']); - $code_texte = addslashes($codes['texte']); - $code_ps = addslashes($codes['ps']); + if (!$codes) $codes = array(); + $codes = addslashes(serialize($codes)); if ($nouveau) { - $query = "INSERT spip_versions (id_article, id_version, permanent, date, id_auteur, chapo, texte, ps) ". - "VALUES ($id_article, $id_version_new, 'non', NOW(), '$connect_id_auteur', '$code_chapo', ". - "'$code_texte', '$code_ps')"; + $query = "INSERT spip_versions (id_article, id_version, permanent, date, id_auteur, champs) ". + "VALUES ($id_article, $id_version_new, 'non', NOW(), '$connect_id_auteur', '$codes')"; spip_query($query); } else { - $query = "UPDATE spip_versions SET date=NOW(), id_auteur=$connect_id_auteur, ". - "chapo='$code_chapo', texte='$code_texte', ps='$code_ps' ". - "WHERE id_article=$id_article AND id_version=$id_version"; + $query = "UPDATE spip_versions SET date=NOW(), id_auteur=$connect_id_auteur, champs='$codes' ". + "WHERE id_article=$id_article AND id_version=$id_version"; spip_query($query); } $query = "UPDATE spip_articles SET id_version=$id_version_new WHERE id_article=$id_article"; @@ -313,4 +299,4 @@ function ajouter_version($id_article, $chapo, $texte, $ps, $extra) { } -?> \ No newline at end of file +?> diff --git a/ecrire/inc_difflcs.php3 b/ecrire/inc_difflcs.php3 new file mode 100644 index 0000000000000000000000000000000000000000..f368be85ba0cf24b5bf5f58c2fe1f33976743a06 --- /dev/null +++ b/ecrire/inc_difflcs.php3 @@ -0,0 +1,355 @@ +<?php + +// Ce fichier ne sera execute qu'une fois +if (defined("_ECRIRE_INC_DIFFLCS")) return; +define("_ECRIRE_INC_DIFFLCS", "1"); + + +// +// LCS (Longest Common Subsequence) en deux versions +// (ref: http://www2.toki.or.id/book/AlgDesignManual/BOOK/BOOK5/NODE208.HTM) + +// Version ultra-simplifiee : chaque chaine est une permutation de l'autre +// et on passe en parametre un des deux tableaux de correspondances +function lcs_opt($s) { + $n = count($s); + if (!$n) return array(); + $paths = array(); + $paths_ymin = array(); + $max_len = 0; + + // Insertion des points + asort($s); + foreach ($s as $y => $c) { + for ($len = $max_len; $len > 0; $len--) { + if ($paths_ymin[$len] < $y) { + $paths_ymin[$len + 1] = $y; + $paths[$len + 1] = $paths[$len]; + $paths[$len + 1][$y] = $c; + break; + } + } + if ($len == 0) { + $paths_ymin[1] = $y; + $paths[1] = array($y => $c); + } + if ($len + 1 > $max_len) $max_len = $len + 1; + } + return $paths[$max_len]; +} + +// Version normale : les deux chaines n'ont pas ete traitees au prealable +// par la fonction d'appariement +function lcs($s, $t) { + $n = count($s); + $p = count($t); + if (!$n || !$p) return array(0 => array(), 1 => array()); + $paths = array(); + $paths_ymin = array(); + $max_len = 0; + $s_pos = $t_pos = array(); + + // Insertion des points + foreach ($t as $y => $c) $t_pos[trim($c)][] = $y; + + foreach ($s as $x => $c) { + $c = trim($c); + if (!$t_pos[$c]) continue; + krsort($t_pos[$c]); + foreach ($t_pos[$c] as $y) { + for ($len = $max_len; $len > 0; $len--) { + if ($paths_ymin[$len] < $y) { + $paths_ymin[$len + 1] = $y; + $paths[$len + 1] = $paths[$len]; + $paths[$len + 1][0][$x] = $y; + $paths[$len + 1][1][$y] = $x; + break; + } + } + if ($len + 1 > $max_len) $max_len = $len + 1; + if ($len == 0) { + $paths_ymin[1] = $y; + $paths[1] = array(0 => array($x => $y), 1 => array($y => $x)); + } + } + } + if ($paths[$max_len]) return $paths[$max_len]; + return array(0 => array(), 1 => array()); +} + + +function test_lcs($a, $b) { + $s = explode(" ", $a); + $t = explode(" ", $b); + + $t0 = explode(" ", microtime()); + list($r1, $r2) = lcs($s, $t); + $t1 = explode(" ", microtime()); + $dt = $t1[0] + $t1[1] - $t0[0] - $t0[1]; + echo join(" ", $r1)."<br />"; + echo join(" ", $r2)."<p>"; + echo "<div style='font-weight: bold; color: red;'>$dt s.</div>"; +} + +function test_lcs_opt($s) { + $s = preg_split(',\s+,', $s); + + $t0 = explode(" ", microtime()); + $t = lcs_opt($s); + $t1 = explode(" ", microtime()); + $dt = $t1[0] + $t1[1] - $t0[0] - $t0[1]; + echo join(" ", $s)."<br />"; + echo join(" ", $t)."<p>"; + echo "<div style='font-weight: bold; color: red;'>$dt s.</div>"; +} + + +// +// Generation de diff a plusieurs etages +// + +class Diff { + var $diff; + var $fuzzy; + + function Diff($diff) { + $this->diff = $diff; + $this->fuzzy = true; + } + + function comparer($new, $old) { + $paras = $this->diff->segmenter($new); + $paras_old = $this->diff->segmenter($old); + if ($this->diff->fuzzy()) { + list($trans_rev, $trans) = apparier_paras($paras_old, $paras); + $lcs = lcs_opt($trans); + $lcs_rev = array_flip($lcs); + } + else { + list($trans_rev, $trans) = lcs($paras_old, $paras); + $lcs = $trans; + $lcs_rev = $trans_rev; + } + + reset($paras_old); + reset($paras); + reset($lcs); + unset($i_old); + $fin_old = false; + foreach ($paras as $i => $p) { + if (!isset($trans[$i])) { + // Paragraphe ajoute + $this->diff->ajouter($p); + continue; + } + $j = $trans[$i]; + if (!isset($lcs[$i])) { + // Paragraphe deplace + $this->diff->deplacer($p, $paras_old[$j]); + continue; + } + if (!$fin_old) { + // Paragraphes supprimes jusqu'au paragraphe courant + if (!isset($i_old)) { + list($i_old, $p_old) = each($paras_old); + if (!$p_old) $fin_old = true; + } + while (!$fin_old && $i_old < $j) { + if (!isset($trans_rev[$i_old])) { + $this->diff->supprimer($p_old); + } + unset($i_old); + list($i_old, $p_old) = each($paras_old); + if (!$p_old) $fin_old = true; + } + } + // Paragraphe n'ayant pas change de place + $this->diff->comparer($p, $paras_old[$j]); + } + // Paragraphes supprimes a la fin du texte + if (!$fin_old) { + if (!isset($i_old)) { + list($i_old, $p_old) = each($paras_old); + if (!strlen($p_old)) $fin_old = true; + } + while (!$fin_old) { + if (!isset($trans_rev[$i_old])) { + $this->diff->supprimer($p_old); + } + list($i_old, $p_old) = each($paras_old); + if (!$p_old) $fin_old = true; + } + } + if (isset($i_old)) { + if (!isset($trans_rev[$i_old])) { + $this->diff->supprimer($p_old); + } + } + return $this->diff->resultat(); + } +} + +class DiffTexte { + var $r; + + function DiffTexte() { + $this->r = ""; + } + + function _diff($p, $p_old) { + $diff = new Diff(new DiffPara); + return $diff->comparer($p, $p_old); + } + + function fuzzy() { + return true; + } + function segmenter($texte) { + return separer_paras($texte); + } + + function ajouter($p) { + $this->r .= "\n\n\n<div class=\"diff-para-ajoute\" title=\""._L('Paragraphe ajouté')."\">".$p."</div>"; + } + function supprimer($p_old) { + $this->r .= "\n\n\n<div class=\"diff-para-supprime\" title=\""._L('Paragraphe supprimé')."\">".$p_old."</div>"; + } + function deplacer($p, $p_old) { + $this->r .= "\n\n\n<div class=\"diff-para-deplace\" title=\""._L('Paragraphe déplacé')."\">"; + $this->r .= $this->_diff($p, $p_old); + $this->r .= "</div>"; + } + function comparer($p, $p_old) { + $this->r .= "\n\n\n".$this->_diff($p, $p_old); + } + + function resultat() { + return $this->r; + } +} + +class DiffPara { + var $r; + + function DiffPara() { + $this->r = ""; + } + + function _diff($p, $p_old) { + $diff = new Diff(new DiffPhrase); + return $diff->comparer($p, $p_old); + } + + function fuzzy() { + return true; + } + function segmenter($texte) { + $paras = array(); + $texte = trim($texte); + while (preg_match('/[\.!\?]+\s*/u', $texte, $regs)) { + $p = strpos($texte, $regs[0]) + strlen($regs[0]); + $paras[] = substr($texte, 0, $p); + $texte = substr($texte, $p); + } + if ($texte) $paras[] = $texte; + return $paras; + } + + function ajouter($p) { + $this->r .= "<span class=\"diff-ajoute\" title=\""._L('Texte ajouté')."\">".$p."</span>"; + } + function supprimer($p_old) { + $this->r .= "<span class=\"diff-supprime\" title=\""._L('Texte supprimé')."\">".$p_old."</span>"; + } + function deplacer($p, $p_old) { + $this->r .= "<span class=\"diff-deplace\" title=\""._L('Texte déplacé')."\">".$this->_diff($p, $p_old)."</span>"; + } + function comparer($p, $p_old) { + $this->r .= $this->_diff($p, $p_old); + } + + function resultat() { + return $this->r; + } +} + +class DiffPhrase { + var $r; + + function DiffPhrase() { + $this->r = ""; + } + + function fuzzy() { + return false; + } + function segmenter($texte) { + $paras = array(); + //$texte = trim($texte); + while (preg_match('/([[:punct:]]+)(\s+|$)|(\s+)([[:punct:]]*)/u', $texte, $regs)) { + $p = strpos($texte, $regs[0]); + $l = strlen($regs[0]); + $punct = $regs[1] ? $regs[1] : $regs[4]; + $milieu = ""; + if ($punct) { + // Attacher les raccourcis fermants au mot precedent + if (preg_match(',^[\]}]+$,', $punct)) { + $avant = substr($texte, 0, $p) . $regs[3] . $punct; + $texte = $regs[2] . substr($texte, $p + $l); + } + // Attacher les raccourcis ouvrants au mot suivant + else if ($regs[3] && preg_match(',^[\[{]+$,', $punct)) { + $avant = substr($texte, 0, $p) . $regs[3]; + $texte = $punct . substr($texte, $p + $l); + } + // Les autres signes de ponctuation sont des mots a part entiere + else { + $avant = substr($texte, 0, $p); + $milieu = $regs[0]; + $texte = substr($texte, $p + $l); + } + } + else { + $avant = substr($texte, 0, $p + $l); + $texte = substr($texte, $p + $l); + } + if ($avant) $paras[] = $avant; + if ($milieu) $paras[] = $milieu; + } + if ($texte) $paras[] = $texte; + return $paras; + } + + function ajouter($p) { + $this->r .= "<span class=\"diff-ajoute\" title=\""._L('Texte ajouté')."\">".$p."</span> "; + } + function supprimer($p_old) { + $this->r .= "<span class=\"diff-supprime\" title=\""._L('Texte supprimé')."\">".$p_old."</span> "; + } + function comparer($p, $p_old) { + $this->r .= $p; + } + + function resultat() { + return $this->r; + } +} + + +function preparer_diff($texte) { + include_ecrire("inc_charsets.php3"); + + $charset = lire_meta('charset'); + if ($charset == 'utf-8') + return unicode_to_utf_8(html2unicode($texte)); + return unicode_to_utf_8(html2unicode(charset2unicode($texte, $charset, true))); +} + +function afficher_diff($texte) { + $charset = lire_meta('charset'); + if ($charset == 'utf-8') return $texte; + return charset2unicode($texte, 'utf-8'); +} + + +?>