X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=www%2Fplugins-dist%2Frevisions%2Finc%2Fdiff.php;fp=www%2Fplugins-dist%2Frevisions%2Finc%2Fdiff.php;h=83741d019432d30497990b2b68cb76f378663fb8;hb=4f443dce95ff6f8221c189880a70c74ce1c1f238;hp=a15266a5efdbda97a94641e18f9d3a1d2762cf16;hpb=4a628e9b277d3617535f99d663ca79fa2e891177;p=lhc%2Fweb%2Fwww.git diff --git a/www/plugins-dist/revisions/inc/diff.php b/www/plugins-dist/revisions/inc/diff.php index a15266a5..83741d01 100644 --- a/www/plugins-dist/revisions/inc/diff.php +++ b/www/plugins-dist/revisions/inc/diff.php @@ -10,19 +10,35 @@ * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. * \***************************************************************************/ +/** + * Fonctions utilitaires du plugin révisions + * + * @package SPIP\Revisions\Diff + **/ + +if (!defined("_ECRIRE_INC_VERSION")) { + return; +} -if (!defined("_ECRIRE_INC_VERSION")) return; -// // 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 -// https://code.spip.net/@lcs_opt +// (ref: http://web.archive.org/web/20071206224029/http://www2.toki.or.id/book/AlgDesignManual/BOOK/BOOK5/NODE208.HTM#SECTION03178000000000000000) + +/** + * Calcule un LCS (Longest Common Subsequence) simplifié + * + * Chaque chaîne est une permutation de l'autre et on passe en paramètre + * un des deux tableaux de correspondances + * + * @see lcs() + * @param array $s + * @return array + **/ function lcs_opt($s) { $n = count($s); - if (!$n) return array(); + if (!$n) { + return array(); + } $paths = array(); $paths_ymin = array(); $max_len = 0; @@ -31,7 +47,9 @@ function lcs_opt($s) { asort($s); $max = 400; foreach ($s as $y => $c) { - if ($max-- < 0) break; # eviter l'explosion memoire des tres gros diff + if ($max-- < 0) { + break; + } # eviter l'explosion memoire des tres gros diff for ($len = $max_len; $len > 0; $len--) { if ($paths_ymin[$len] < $y) { $paths_ymin[$len + 1] = $y; @@ -44,29 +62,45 @@ function lcs_opt($s) { $paths_ymin[1] = $y; $paths[1] = array($y => $c); } - if ($len + 1 > $max_len) $max_len = $len + 1; + 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 -// https://code.spip.net/@lcs +/** + * Calcule un LCS (Longest Common Subsequence) + * + * Les deux chaînes n'ont pas été traitées au préalable par la fonction d'appariement + * + * @see lcs_opt() + * @param array $s + * @param array $t + * @return array + **/ function lcs($s, $t) { $n = count($s); $p = count($t); - if (!$n || !$p) return array(0 => array(), 1 => array()); + 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 ($t as $y => $c) { + $t_pos[trim($c)][] = $y; + } foreach ($s as $x => $c) { $c = trim($c); - if (!isset($t_pos[$c])) continue; + if (!isset($t_pos[$c])) { + continue; + } krsort($t_pos[$c]); foreach ($t_pos[$c] as $y) { for ($len = $max_len; $len > 0; $len--) { @@ -74,18 +108,20 @@ function lcs($s, $t) { $paths_ymin[$len + 1] = $y; // On construit le resultat sous forme de chaine d'abord, // car les tableaux de PHP sont dispendieux en taille memoire - $paths[$len + 1] = $paths[$len]." $x,$y"; + $paths[$len + 1] = $paths[$len] . " $x,$y"; break; } } - if ($len + 1 > $max_len) $max_len = $len + 1; + if ($len + 1 > $max_len) { + $max_len = $len + 1; + } if ($len == 0) { $paths_ymin[1] = $y; $paths[1] = "$x,$y"; } } } - if (isset($paths[$max_len]) AND $paths[$max_len]) { + if (isset($paths[$max_len]) and $paths[$max_len]) { $path = explode(" ", $paths[$max_len]); $u = $v = array(); foreach ($path as $p) { @@ -93,41 +129,51 @@ function lcs($s, $t) { $u[$x] = $y; $v[$y] = $x; } + return array($u, $v); } + return array(0 => array(), 1 => array()); } -// -// Generation de diff a plusieurs etages -// - -// https://code.spip.net/@Diff +/** + * Génération de diff a plusieurs étages + * + * @package SPIP\Revisions\Diff + **/ class Diff { - var $diff; - var $fuzzy; - -// https://code.spip.net/@Diff - function Diff($diff) { + /** + * Objet DiffX d'un texte ou partie de texte + * + * @var Object Objet Diff* (DiffTexte, DiffPara, DiffPhrase) + */ + public $diff; + public $fuzzy; + + /** + * Constructeur + * + * @param Object $diff Objet Diff* d'un texte ou morceau de texte + **/ + public function __construct($diff) { $this->diff = $diff; $this->fuzzy = true; } // https://code.spip.net/@comparer - function comparer($new, $old) { + public 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 { + } else { list($trans_rev, $trans) = lcs($paras_old, $paras); $lcs = $trans; $lcs_rev = $trans_rev; } - + reset($paras_old); reset($paras); reset($lcs); @@ -149,7 +195,9 @@ class Diff { // Paragraphes supprimes jusqu'au paragraphe courant if (!isset($i_old)) { list($i_old, $p_old) = each($paras_old); - if (!$p_old) $fin_old = true; + if (!$p_old) { + $fin_old = true; + } } while (!$fin_old && $i_old < $j) { if (!isset($trans_rev[$i_old])) { @@ -157,7 +205,9 @@ class Diff { } unset($i_old); list($i_old, $p_old) = each($paras_old); - if (!$p_old) $fin_old = true; + if (!$p_old) { + $fin_old = true; + } } } // Paragraphe n'ayant pas change de place @@ -167,14 +217,18 @@ class Diff { if (!$fin_old) { if (!isset($i_old)) { list($i_old, $p_old) = each($paras_old); - if (!strlen($p_old)) $fin_old = true; + 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 (!$p_old) { + $fin_old = true; + } } } if (isset($i_old)) { @@ -182,83 +236,106 @@ class Diff { $this->diff->supprimer($p_old); } } + return $this->diff->resultat(); } } -// https://code.spip.net/@DiffTexte +/** + * Génération de diff sur un Texte + * + * @package SPIP\Revisions\Diff + **/ class DiffTexte { - var $r; + public $r; -// https://code.spip.net/@DiffTexte - function DiffTexte() { + /** + * Constructeur + **/ + public function __construct() { $this->r = ""; } // https://code.spip.net/@_diff - function _diff($p, $p_old) { + public function _diff($p, $p_old) { $diff = new Diff(new DiffPara); + return $diff->comparer($p, $p_old); } // https://code.spip.net/@fuzzy - function fuzzy() { + public function fuzzy() { return true; } -// https://code.spip.net/@segmenter - function segmenter($texte) { + + /** + * Découper les paragraphes d'un texte en fragments + * + * @param string $texte Texte à fragmenter + * @return string[] Tableau de fragments (paragraphes) + **/ + public function segmenter($texte) { return separer_paras($texte); } // NB : rem=\"diff-\" est un signal pour la fonction "afficher_para_modifies" // https://code.spip.net/@ajouter - function ajouter($p) { + public function ajouter($p) { $p = trim($p); - $this->r .= "\n\n\n".$p.""; + $this->r .= "\n\n\n" . $p . ""; } + // https://code.spip.net/@supprimer - function supprimer($p_old) { + public function supprimer($p_old) { $p_old = trim($p_old); - $this->r .= "\n\n\n".$p_old.""; + $this->r .= "\n\n\n" . $p_old . ""; } + // https://code.spip.net/@deplacer - function deplacer($p, $p_old) { - $this->r .= "\n\n\n"; + public function deplacer($p, $p_old) { + $this->r .= "\n\n\n"; $this->r .= trim($this->_diff($p, $p_old)); $this->r .= ""; } + // https://code.spip.net/@comparer - function comparer($p, $p_old) { - $this->r .= "\n\n\n".$this->_diff($p, $p_old); + public function comparer($p, $p_old) { + $this->r .= "\n\n\n" . $this->_diff($p, $p_old); } - + // https://code.spip.net/@resultat - function resultat() { + public function resultat() { return $this->r; } } -// https://code.spip.net/@DiffPara +/** + * Génération de diff sur un paragraphe + * + * @package SPIP\Revisions\Diff + **/ class DiffPara { - var $r; + public $r; -// https://code.spip.net/@DiffPara - function DiffPara() { + /** Constructeur */ + public function __construct() { $this->r = ""; } // https://code.spip.net/@_diff - function _diff($p, $p_old) { + public function _diff($p, $p_old) { $diff = new Diff(new DiffPhrase); + return $diff->comparer($p, $p_old); } // https://code.spip.net/@fuzzy - function fuzzy() { + public function fuzzy() { return true; } + // https://code.spip.net/@segmenter - function segmenter($texte) { + public function segmenter($texte) { $paras = array(); $texte = trim($texte); while (preg_match('/[\.!\?\]]+\s*/u', $texte, $regs)) { @@ -266,59 +343,70 @@ class DiffPara { $paras[] = substr($texte, 0, $p); $texte = substr($texte, $p); } - if ($texte) $paras[] = $texte; + if ($texte) { + $paras[] = $texte; + } + return $paras; } // https://code.spip.net/@ajouter - function ajouter($p) { - $this->r .= "".$p.""; + public function ajouter($p) { + $this->r .= "" . $p . ""; } + // https://code.spip.net/@supprimer - function supprimer($p_old) { - $this->r .= "".$p_old.""; + public function supprimer($p_old) { + $this->r .= "" . $p_old . ""; } + // https://code.spip.net/@deplacer - function deplacer($p, $p_old) { - $this->r .= "".$this->_diff($p, $p_old).""; + public function deplacer($p, $p_old) { + $this->r .= "" . $this->_diff($p, + $p_old) . ""; } + // https://code.spip.net/@comparer - function comparer($p, $p_old) { + public function comparer($p, $p_old) { $this->r .= $this->_diff($p, $p_old); } - + // https://code.spip.net/@resultat - function resultat() { + public function resultat() { return $this->r; } } -// https://code.spip.net/@DiffPhrase +/** + * Génération de diff sur une phrase + * + * @package SPIP\Revisions\Diff + **/ class DiffPhrase { - var $r; + public $r; -// https://code.spip.net/@DiffPhrase - function DiffPhrase() { + /** Constructeur */ + public function __construct() { $this->r = ""; } // https://code.spip.net/@fuzzy - function fuzzy() { + public function fuzzy() { return false; } + // https://code.spip.net/@segmenter - function segmenter($texte) { + public function segmenter($texte) { $paras = array(); if (test_pcre_unicode()) { - $punct = '([[:punct:]]|'.plage_punct_unicode().')'; + $punct = '([[:punct:]]|' . plage_punct_unicode() . ')'; $mode = 'u'; - } - else { + } else { // Plages de poncutation pour preg_match bugge (ha ha) - $punct = '([^\w\s\x80-\xFF]|'.plage_punct_unicode().')'; + $punct = '([^\w\s\x80-\xFF]|' . plage_punct_unicode() . ')'; $mode = ''; } - $preg = '/('.$punct.'+)(\s+|$)|(\s+)('.$punct.'*)/'.$mode; + $preg = '/(' . $punct . '+)(\s+|$)|(\s+)(' . $punct . '*)/' . $mode; while (preg_match($preg, $texte, $regs)) { $p = strpos($texte, $regs[0]); $l = strlen($regs[0]); @@ -329,56 +417,64 @@ class DiffPhrase { if ($punct == '[[') { $avant = substr($texte, 0, $p) . $regs[5] . $punct; $texte = $regs[4] . substr($texte, $p + $l); + } else { + if ($punct == ']]') { + $avant = substr($texte, 0, $p) . $regs[5] . $punct; + $texte = substr($texte, $p + $l); + } // Attacher les raccourcis fermants au mot precedent + else { + if (preg_match(',^[\]}]+$,', $punct)) { + $avant = substr($texte, 0, $p) . (isset($regs[5]) ? $regs[5] : '') . $punct; + $texte = $regs[4] . substr($texte, $p + $l); + } // Attacher les raccourcis ouvrants au mot suivant + else { + if (isset($regs[5]) && $regs[5] && preg_match(',^[\[{]+$,', $punct)) { + $avant = substr($texte, 0, $p) . $regs[5]; + $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 - if ($punct == ']]') { - $avant = substr($texte, 0, $p) . $regs[5] . $punct; - $texte = substr($texte, $p + $l); - } - // Attacher les raccourcis fermants au mot precedent - else - if (preg_match(',^[\]}]+$,', $punct)) { - $avant = substr($texte, 0, $p) . (isset($regs[5])?$regs[5]:'') . $punct; - $texte = $regs[4] . substr($texte, $p + $l); - } - // Attacher les raccourcis ouvrants au mot suivant - else if (isset($regs[5]) && $regs[5] && preg_match(',^[\[{]+$,', $punct)) { - $avant = substr($texte, 0, $p) . $regs[5]; - $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 { + } else { $avant = substr($texte, 0, $p + $l); $texte = substr($texte, $p + $l); } - if ($avant) $paras[] = $avant; - if ($milieu) $paras[] = $milieu; + if ($avant) { + $paras[] = $avant; + } + if ($milieu) { + $paras[] = $milieu; + } } - if ($texte) $paras[] = $texte; + if ($texte) { + $paras[] = $texte; + } + return $paras; } // https://code.spip.net/@ajouter - function ajouter($p) { - $this->r .= "".$p." "; + public function ajouter($p) { + $this->r .= "" . $p . " "; } + // https://code.spip.net/@supprimer - function supprimer($p_old) { - $this->r .= "".$p_old." "; + public function supprimer($p_old) { + $this->r .= "" . $p_old . " "; } + // https://code.spip.net/@comparer - function comparer($p, $p_old) { + public function comparer($p, $p_old) { $this->r .= $p; } // https://code.spip.net/@resultat - function resultat() { + public function resultat() { return $this->r; } } @@ -389,17 +485,19 @@ function preparer_diff($texte) { include_spip('inc/charsets'); $charset = $GLOBALS['meta']['charset']; - if ($charset == 'utf-8') + if ($charset == 'utf-8') { return unicode_to_utf_8(html2unicode($texte)); + } + return unicode_to_utf_8(html2unicode(charset2unicode($texte, $charset, true))); } // https://code.spip.net/@afficher_diff function afficher_diff($texte) { $charset = $GLOBALS['meta']['charset']; - if ($charset == 'utf-8') return $texte; + if ($charset == 'utf-8') { + return $texte; + } + return charset2unicode($texte, 'utf-8'); } - - -?>