[SPIP][PLUGINS] v3.0-->v3.2
[lhc/web/www.git] / www / plugins-dist / revisions / inc / diff.php
index a15266a..83741d0 100644 (file)
  *  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<span class=\"diff-para-ajoute\" title=\""._T('revisions:diff_para_ajoute')."\">".$p."</span rem=\"diff-\">";
+               $this->r .= "\n\n\n<span class=\"diff-para-ajoute\" title=\"" . _T('revisions:diff_para_ajoute') . "\">" . $p . "</span rem=\"diff-\">";
        }
+
 // https://code.spip.net/@supprimer
-       function supprimer($p_old) {
+       public function supprimer($p_old) {
                $p_old = trim($p_old);
-               $this->r .= "\n\n\n<span class=\"diff-para-supprime\" title=\""._T('revisions:diff_para_supprime')."\">".$p_old."</span rem=\"diff-\">";
+               $this->r .= "\n\n\n<span class=\"diff-para-supprime\" title=\"" . _T('revisions:diff_para_supprime') . "\">" . $p_old . "</span rem=\"diff-\">";
        }
+
 // https://code.spip.net/@deplacer
-       function deplacer($p, $p_old) {
-               $this->r .= "\n\n\n<span class=\"diff-para-deplace\" title=\""._T('revisions:diff_para_deplace')."\">";
+       public function deplacer($p, $p_old) {
+               $this->r .= "\n\n\n<span class=\"diff-para-deplace\" title=\"" . _T('revisions:diff_para_deplace') . "\">";
                $this->r .= trim($this->_diff($p, $p_old));
                $this->r .= "</span rem=\"diff-\">";
        }
+
 // 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 .= "<span class=\"diff-ajoute\" title=\""._T('revisions:diff_texte_ajoute')."\">".$p."</span rem=\"diff-\">";
+       public function ajouter($p) {
+               $this->r .= "<span class=\"diff-ajoute\" title=\"" . _T('revisions:diff_texte_ajoute') . "\">" . $p . "</span rem=\"diff-\">";
        }
+
 // https://code.spip.net/@supprimer
-       function supprimer($p_old) {
-               $this->r .= "<span class=\"diff-supprime\" title=\""._T('revisions:diff_texte_supprime')."\">".$p_old."</span rem=\"diff-\">";
+       public function supprimer($p_old) {
+               $this->r .= "<span class=\"diff-supprime\" title=\"" . _T('revisions:diff_texte_supprime') . "\">" . $p_old . "</span rem=\"diff-\">";
        }
+
 // https://code.spip.net/@deplacer
-       function deplacer($p, $p_old) {
-               $this->r .= "<span class=\"diff-deplace\" title=\""._T('revisions:diff_texte_deplace')."\">".$this->_diff($p, $p_old)."</span rem=\"diff-\">";
+       public function deplacer($p, $p_old) {
+               $this->r .= "<span class=\"diff-deplace\" title=\"" . _T('revisions:diff_texte_deplace') . "\">" . $this->_diff($p,
+                               $p_old) . "</span rem=\"diff-\">";
        }
+
 // 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 .= "<span class=\"diff-ajoute\" title=\""._T('revisions:diff_texte_ajoute')."\">".$p."</span rem=\"diff-\"> ";
+       public function ajouter($p) {
+               $this->r .= "<span class=\"diff-ajoute\" title=\"" . _T('revisions:diff_texte_ajoute') . "\">" . $p . "</span rem=\"diff-\"> ";
        }
+
 // https://code.spip.net/@supprimer
-       function supprimer($p_old) {
-               $this->r .= "<span class=\"diff-supprime\" title=\""._T('revisions:diff_texte_supprime')."\">".$p_old."</span rem=\"diff-\"> ";
+       public function supprimer($p_old) {
+               $this->r .= "<span class=\"diff-supprime\" title=\"" . _T('revisions:diff_texte_supprime') . "\">" . $p_old . "</span rem=\"diff-\"> ";
        }
+
 // 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');
 }
-
-
-?>