Verzeichnisstruktur phpBB-3.0.0


Veröffentlicht
12.12.2007

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

diff.php

Zuletzt modifiziert: 09.10.2024, 12:51 - Dateigröße: 14.51 KiB


 001  <?php
 002  /**
 003  *
 004  * @package diff
 005  * @version $Id$
 006  * @copyright (c) 2006 phpBB Group
 007  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 008  *
 009  */
 010   
 011  /**
 012  * @ignore
 013  */
 014  if (!defined('IN_PHPBB'))
 015  {
 016      exit;
 017  }
 018   
 019  /**
 020  * Code from pear.php.net, Text_Diff-0.2.1 (beta) package
 021  * http://pear.php.net/package/Text_Diff/
 022  *
 023  * Modified by phpBB Group to meet our coding standards
 024  * and being able to integrate into phpBB
 025  *
 026  * General API for generating and formatting diffs - the differences between
 027  * two sequences of strings.
 028  *
 029  * @package diff
 030  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
 031  */
 032  class diff
 033  {
 034      /**
 035      * Array of changes.
 036      * @var array
 037      */
 038      var $_edits;
 039   
 040      /**
 041      * Computes diffs between sequences of strings.
 042      *
 043      * @param array $from_lines  An array of strings. Typically these are lines from a file.
 044      * @param array $to_lines    An array of strings.
 045      */
 046      function diff(&$from_content, &$to_content, $preserve_cr = true)
 047      {
 048          $diff_engine = &new diff_engine();
 049          $this->_edits = $diff_engine->diff($from_content, $to_content, $preserve_cr);
 050      }
 051   
 052      /**
 053      * Returns the array of differences.
 054      */
 055      function get_diff()
 056      {
 057          return $this->_edits;
 058      }
 059   
 060      /**
 061      * Computes a reversed diff.
 062      *
 063      * Example:
 064      * <code>
 065      * $diff = &new diff($lines1, $lines2);
 066      * $rev = $diff->reverse();
 067      * </code>
 068      *
 069      * @return diff  A Diff object representing the inverse of the original diff.
 070      *               Note that we purposely don't return a reference here, since
 071      *               this essentially is a clone() method.
 072      */
 073      function reverse()
 074      {
 075          if (version_compare(zend_version(), '2', '>'))
 076          {
 077              $rev = clone($this);
 078          }
 079          else
 080          {
 081              $rev = $this;
 082          }
 083   
 084          $rev->_edits = array();
 085   
 086          foreach ($this->_edits as $edit)
 087          {
 088              $rev->_edits[] = $edit->reverse();
 089          }
 090   
 091          return $rev;
 092      }
 093   
 094      /**
 095      * Checks for an empty diff.
 096      *
 097      * @return boolean  True if two sequences were identical.
 098      */
 099      function is_empty()
 100      {
 101          foreach ($this->_edits as $edit)
 102          {
 103              if (!is_a($edit, 'diff_op_copy'))
 104              {
 105                  return false;
 106              }
 107          }
 108          return true;
 109      }
 110   
 111      /**
 112      * Computes the length of the Longest Common Subsequence (LCS).
 113      *
 114      * This is mostly for diagnostic purposes.
 115      *
 116      * @return integer  The length of the LCS.
 117      */
 118      function lcs()
 119      {
 120          $lcs = 0;
 121   
 122          foreach ($this->_edits as $edit)
 123          {
 124              if (is_a($edit, 'diff_op_copy'))
 125              {
 126                  $lcs += sizeof($edit->orig);
 127              }
 128          }
 129          return $lcs;
 130      }
 131   
 132      /**
 133      * Gets the original set of lines.
 134      *
 135      * This reconstructs the $from_lines parameter passed to the constructor.
 136      *
 137      * @return array  The original sequence of strings.
 138      */
 139      function get_original()
 140      {
 141          $lines = array();
 142   
 143          foreach ($this->_edits as $edit)
 144          {
 145              if ($edit->orig)
 146              {
 147                  array_splice($lines, sizeof($lines), 0, $edit->orig);
 148              }
 149          }
 150          return $lines;
 151      }
 152   
 153      /**
 154      * Gets the final set of lines.
 155      *
 156      * This reconstructs the $to_lines parameter passed to the constructor.
 157      *
 158      * @return array  The sequence of strings.
 159      */
 160      function get_final()
 161      {
 162          $lines = array();
 163   
 164          foreach ($this->_edits as $edit)
 165          {
 166              if ($edit->final)
 167              {
 168                  array_splice($lines, sizeof($lines), 0, $edit->final);
 169              }
 170          }
 171          return $lines;
 172      }
 173   
 174      /**
 175      * Removes trailing newlines from a line of text. This is meant to be used with array_walk().
 176      *
 177      * @param string &$line  The line to trim.
 178      * @param integer $key  The index of the line in the array. Not used.
 179      */
 180      function trim_newlines(&$line, $key)
 181      {
 182          $line = str_replace(array("\n", "\r"), '', $line);
 183      }
 184   
 185      /**
 186      * Checks a diff for validity.
 187      *
 188      * This is here only for debugging purposes.
 189      */
 190      function _check($from_lines, $to_lines)
 191      {
 192          if (serialize($from_lines) != serialize($this->get_original()))
 193          {
 194              trigger_error("[diff] Reconstructed original doesn't match", E_USER_ERROR);
 195          }
 196   
 197          if (serialize($to_lines) != serialize($this->get_final()))
 198          {
 199              trigger_error("[diff] Reconstructed final doesn't match", E_USER_ERROR);
 200          }
 201   
 202          $rev = $this->reverse();
 203   
 204          if (serialize($to_lines) != serialize($rev->get_original()))
 205          {
 206              trigger_error("[diff] Reversed original doesn't match", E_USER_ERROR);
 207          }
 208   
 209          if (serialize($from_lines) != serialize($rev->get_final()))
 210          {
 211              trigger_error("[diff] Reversed final doesn't match", E_USER_ERROR);
 212          }
 213   
 214          $prevtype = null;
 215   
 216          foreach ($this->_edits as $edit)
 217          {
 218              if ($prevtype == get_class($edit))
 219              {
 220                  trigger_error("[diff] Edit sequence is non-optimal", E_USER_ERROR);
 221              }
 222              $prevtype = get_class($edit);
 223          }
 224   
 225          return true;
 226      }
 227  }
 228   
 229  /**
 230  * @package diff
 231  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
 232  */
 233  class mapped_diff extends diff
 234  {
 235      /**
 236      * Computes a diff between sequences of strings.
 237      *
 238      * This can be used to compute things like case-insensitve diffs, or diffs
 239      * which ignore changes in white-space.
 240      *
 241      * @param array $from_lines         An array of strings.
 242      * @param array $to_lines           An array of strings.
 243      * @param array $mapped_from_lines  This array should have the same size number of elements as $from_lines.
 244      *                                  The elements in $mapped_from_lines and $mapped_to_lines are what is actually
 245      *                                  compared when computing the diff.
 246      * @param array $mapped_to_lines    This array should have the same number of elements as $to_lines.
 247      */
 248      function mapped_diff(&$from_lines, &$to_lines, &$mapped_from_lines, &$mapped_to_lines)
 249      {
 250          if (sizeof($from_lines) != sizeof($mapped_from_lines) || sizeof($to_lines) != sizeof($mapped_to_lines))
 251          {
 252              return false;
 253          }
 254   
 255          parent::diff($mapped_from_lines, $mapped_to_lines);
 256   
 257          $xi = $yi = 0;
 258          for ($i = 0; $i < sizeof($this->_edits); $i++)
 259          {
 260              $orig = &$this->_edits[$i]->orig;
 261              if (is_array($orig))
 262              {
 263                  $orig = array_slice($from_lines, $xi, sizeof($orig));
 264                  $xi += sizeof($orig);
 265              }
 266   
 267              $final = &$this->_edits[$i]->final;
 268              if (is_array($final))
 269              {
 270                  $final = array_slice($to_lines, $yi, sizeof($final));
 271                  $yi += sizeof($final);
 272              }
 273          }
 274      }
 275  }
 276   
 277  /**
 278  * @package diff
 279  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
 280  *
 281  * @access private
 282  */
 283  class diff_op
 284  {
 285      var $orig;
 286      var $final;
 287   
 288      function reverse()
 289      {
 290          trigger_error('[diff] Abstract method', E_USER_ERROR);
 291      }
 292   
 293      function norig()
 294      {
 295          return ($this->orig) ? sizeof($this->orig) : 0;
 296      }
 297   
 298      function nfinal()
 299      {
 300          return ($this->final) ? sizeof($this->final) : 0;
 301      }
 302  }
 303   
 304  /**
 305  * @package diff
 306  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
 307  *
 308  * @access private
 309  */
 310  class diff_op_copy extends diff_op
 311  {
 312      function diff_op_copy($orig, $final = false)
 313      {
 314          if (!is_array($final))
 315          {
 316              $final = $orig;
 317          }
 318          $this->orig = $orig;
 319          $this->final = $final;
 320      }
 321   
 322      function &reverse()
 323      {
 324          $reverse = &new diff_op_copy($this->final, $this->orig);
 325          return $reverse;
 326      }
 327  }
 328   
 329  /**
 330  * @package diff
 331  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
 332  *
 333  * @access private
 334  */
 335  class diff_op_delete extends diff_op
 336  {
 337      function diff_op_delete($lines)
 338      {
 339          $this->orig = $lines;
 340          $this->final = false;
 341      }
 342   
 343      function &reverse()
 344      {
 345          $reverse = &new diff_op_add($this->orig);
 346          return $reverse;
 347      }
 348  }
 349   
 350  /**
 351  * @package diff
 352  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
 353  *
 354  * @access private
 355  */
 356  class diff_op_add extends diff_op
 357  {
 358      function diff_op_add($lines)
 359      {
 360          $this->final = $lines;
 361          $this->orig = false;
 362      }
 363   
 364      function &reverse()
 365      {
 366          $reverse = &new diff_op_delete($this->final);
 367          return $reverse;
 368      }
 369  }
 370   
 371  /**
 372  * @package diff
 373  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
 374  *
 375  * @access private
 376  */
 377  class diff_op_change extends diff_op
 378  {
 379      function diff_op_change($orig, $final)
 380      {
 381          $this->orig = $orig;
 382          $this->final = $final;
 383      }
 384   
 385      function &reverse()
 386      {
 387          $reverse = &new diff_op_change($this->final, $this->orig);
 388          return $reverse;
 389      }
 390  }
 391   
 392   
 393  /**
 394  * A class for computing three way diffs.
 395  *
 396  * @package diff
 397  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
 398  */
 399  class diff3 extends diff
 400  {
 401      /**
 402      * Conflict counter.
 403      * @var integer
 404      */
 405      var $_conflicting_blocks = 0;
 406   
 407      /**
 408      * Computes diff between 3 sequences of strings.
 409      *
 410      * @param array $orig    The original lines to use.
 411      * @param array $final1  The first version to compare to.
 412      * @param array $final2  The second version to compare to.
 413      */
 414      function diff3(&$orig, &$final1, &$final2)
 415      {
 416          $diff_engine = &new diff_engine();
 417   
 418          $diff_1 = $diff_engine->diff($orig, $final1);
 419          $diff_2 = $diff_engine->diff($orig, $final2);
 420   
 421          unset($engine);
 422   
 423          $this->_edits = $this->_diff3($diff_1, $diff_2);
 424      }
 425   
 426      /**
 427      * Return merged output
 428      *
 429      * @param string $label1 the cvs file version/label from the original set of lines
 430      * @param string $label2 the cvs file version/label from the new set of lines
 431      * @param string $label_sep the explanation between label1 and label2 - more of a helper for the user
 432      * @param bool $get_conflicts if set to true only the number of conflicts is returned
 433      * @param bool $merge_new if set to true the merged output will have the new file contents on a conflicting merge
 434      *
 435      * @return mixed the merged output
 436      */
 437      function merged_output($label1 = 'CURRENT_FILE', $label2 = 'NEW_FILE', $label_sep = 'DIFF_SEP_EXPLAIN', $get_conflicts = false, $merge_new = false)
 438      {
 439          global $user;
 440   
 441          if ($get_conflicts)
 442          {
 443              foreach ($this->_edits as $edit)
 444              {
 445                  if ($edit->is_conflict())
 446                  {
 447                      $this->_conflicting_blocks++;
 448                  }
 449              }
 450   
 451              return $this->_conflicting_blocks;
 452          }
 453   
 454          $label1 = (!empty($user->lang[$label1])) ? $user->lang[$label1] : $label1;
 455          $label2 = (!empty($user->lang[$label2])) ? $user->lang[$label2] : $label2;
 456          $label_sep = (!empty($user->lang[$label_sep])) ? $user->lang[$label_sep] : $label_sep;
 457   
 458          $lines = array();
 459   
 460          foreach ($this->_edits as $edit)
 461          {
 462              if ($edit->is_conflict())
 463              {
 464                  if (!$merge_new)
 465                  {
 466                      $lines = array_merge($lines, array('<<<<<<<' . ($label1 ? ' ' . $label1 : '')), $edit->final1, array('=======' . ($label_sep ? ' ' . $label_sep : '')), $edit->final2, array('>>>>>>>' . ($label2 ? ' ' . $label2 : '')));
 467                  }
 468                  else
 469                  {
 470                      $lines = array_merge($lines, $edit->final1);
 471                  }
 472                  $this->_conflicting_blocks++;
 473              }
 474              else
 475              {
 476                  $lines = array_merge($lines, $edit->merged());
 477              }
 478          }
 479   
 480          return $lines;
 481      }
 482   
 483      /**
 484      * Merge the output and use the new file code for conflicts
 485      */
 486      function merged_new_output()
 487      {
 488          $lines = array();
 489   
 490          foreach ($this->_edits as $edit)
 491          {
 492              if ($edit->is_conflict())
 493              {
 494                  $lines = array_merge($lines, $edit->final2);
 495              }
 496              else
 497              {
 498                  $lines = array_merge($lines, $edit->merged());
 499              }
 500          }
 501   
 502          return $lines;
 503      }
 504   
 505      /**
 506      * Merge the output and use the original file code for conflicts
 507      */
 508      function merged_orig_output()
 509      {
 510          $lines = array();
 511   
 512          foreach ($this->_edits as $edit)
 513          {
 514              if ($edit->is_conflict())
 515              {
 516                  $lines = array_merge($lines, $edit->final1);
 517              }
 518              else
 519              {
 520                  $lines = array_merge($lines, $edit->merged());
 521              }
 522          }
 523   
 524          return $lines;
 525      }
 526   
 527      /**
 528      * Get conflicting block(s)
 529      */
 530      function get_conflicts()
 531      {
 532          $conflicts = array();
 533   
 534          foreach ($this->_edits as $edit)
 535          {
 536              if ($edit->is_conflict())
 537              {
 538                  $conflicts[] = array($edit->final1, $edit->final2);
 539              }
 540          }
 541   
 542          return $conflicts;
 543      }
 544   
 545      /**
 546      * @access private
 547      */
 548      function _diff3(&$edits1, &$edits2)
 549      {
 550          $edits = array();
 551          $bb = &new diff3_block_builder();
 552   
 553          $e1 = current($edits1);
 554          $e2 = current($edits2);
 555   
 556          while ($e1 || $e2)
 557          {
 558              if ($e1 && $e2 && is_a($e1, 'diff_op_copy') && is_a($e2, 'diff_op_copy'))
 559              {
 560                  // We have copy blocks from both diffs. This is the (only) time we want to emit a diff3 copy block.
 561                  // Flush current diff3 diff block, if any.
 562                  if ($edit = $bb->finish())
 563                  {
 564                      $edits[] = $edit;
 565                  }
 566   
 567                  $ncopy = min($e1->norig(), $e2->norig());
 568                  $edits[] = &new diff3_op_copy(array_slice($e1->orig, 0, $ncopy));
 569   
 570                  if ($e1->norig() > $ncopy)
 571                  {
 572                      array_splice($e1->orig, 0, $ncopy);
 573                      array_splice($e1->final, 0, $ncopy);
 574                  }
 575                  else
 576                  {
 577                      $e1 = next($edits1);
 578                  }
 579   
 580                  if ($e2->norig() > $ncopy)
 581                  {
 582                      array_splice($e2->orig, 0, $ncopy);
 583                      array_splice($e2->final, 0, $ncopy);
 584                  }
 585                  else
 586                  {
 587                      $e2 = next($edits2);
 588                  }
 589              }
 590              else
 591              {
 592                  if ($e1 && $e2)
 593                  {
 594                      if ($e1->orig && $e2->orig)
 595                      {
 596                          $norig = min($e1->norig(), $e2->norig());
 597                          $orig = array_splice($e1->orig, 0, $norig);
 598                          array_splice($e2->orig, 0, $norig);
 599                          $bb->input($orig);
 600                      }
 601                      else
 602                      {
 603                          $norig = 0;
 604                      }
 605   
 606                      if (is_a($e1, 'diff_op_copy'))
 607                      {
 608                          $bb->out1(array_splice($e1->final, 0, $norig));
 609                      }
 610   
 611                      if (is_a($e2, 'diff_op_copy'))
 612                      {
 613                          $bb->out2(array_splice($e2->final, 0, $norig));
 614                      }
 615                  }
 616   
 617                  if ($e1 && ! $e1->orig)
 618                  {
 619                      $bb->out1($e1->final);
 620                      $e1 = next($edits1);
 621                  }
 622   
 623                  if ($e2 && ! $e2->orig)
 624                  {
 625                      $bb->out2($e2->final);
 626                      $e2 = next($edits2);
 627                  }
 628              }
 629          }
 630   
 631          if ($edit = $bb->finish())
 632          {
 633              $edits[] = $edit;
 634          }
 635   
 636          return $edits;
 637      }
 638  }
 639   
 640  /**
 641  * @package diff
 642  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
 643  *
 644  * @access private
 645  */
 646  class diff3_op
 647  {
 648      function diff3_op($orig = false, $final1 = false, $final2 = false)
 649      {
 650          $this->orig = $orig ? $orig : array();
 651          $this->final1 = $final1 ? $final1 : array();
 652          $this->final2 = $final2 ? $final2 : array();
 653      }
 654   
 655      function merged()
 656      {
 657          if (!isset($this->_merged))
 658          {
 659              if ($this->final1 === $this->final2)
 660              {
 661                  $this->_merged = &$this->final1;
 662              }
 663              else if ($this->final1 === $this->orig)
 664              {
 665                  $this->_merged = &$this->final2;
 666              }
 667              else if ($this->final2 === $this->orig)
 668              {
 669                  $this->_merged = &$this->final1;
 670              }
 671              else
 672              {
 673                  $this->_merged = false;
 674              }
 675          }
 676   
 677          return $this->_merged;
 678      }
 679   
 680      function is_conflict()
 681      {
 682          return ($this->merged() === false) ? true : false;
 683      }
 684  }
 685   
 686  /**
 687  * @package diff
 688  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
 689  *
 690  * @access private
 691  */
 692  class diff3_op_copy extends diff3_op
 693  {
 694      function diff3_op_copy($lines = false)
 695      {
 696          $this->orig = $lines ? $lines : array();
 697          $this->final1 = &$this->orig;
 698          $this->final2 = &$this->orig;
 699      }
 700   
 701      function merged()
 702      {
 703          return $this->orig;
 704      }
 705   
 706      function is_conflict()
 707      {
 708          return false;
 709      }
 710  }
 711   
 712  /**
 713  * @package diff
 714  * @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
 715  *
 716  * @access private
 717  */
 718  class diff3_block_builder
 719  {
 720      function diff3_block_builder()
 721      {
 722          $this->_init();
 723      }
 724   
 725      function input($lines)
 726      {
 727          if ($lines)
 728          {
 729              $this->_append($this->orig, $lines);
 730          }
 731      }
 732   
 733      function out1($lines)
 734      {
 735          if ($lines)
 736          {
 737              $this->_append($this->final1, $lines);
 738          }
 739      }
 740   
 741      function out2($lines)
 742      {
 743          if ($lines)
 744          {
 745              $this->_append($this->final2, $lines);
 746          }
 747      }
 748   
 749      function is_empty()
 750      {
 751          return !$this->orig && !$this->final1 && !$this->final2;
 752      }
 753   
 754      function finish()
 755      {
 756          if ($this->is_empty())
 757          {
 758              return false;
 759          }
 760          else
 761          {
 762              $edit = &new diff3_op($this->orig, $this->final1, $this->final2);
 763              $this->_init();
 764              return $edit;
 765          }
 766      }
 767   
 768      function _init()
 769      {
 770          $this->orig = $this->final1 = $this->final2 = array();
 771      }
 772   
 773      function _append(&$array, $lines)
 774      {
 775          array_splice($array, sizeof($array), 0, $lines);
 776      }
 777  }
 778   
 779  ?>