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  ?>