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

renderer.php

Zuletzt modifiziert: 09.10.2024, 12:51 - Dateigröße: 17.63 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  * A class to render Diffs in different formats.
027  *
028  * This class renders the diff in classic diff format. It is intended that
029  * this class be customized via inheritance, to obtain fancier outputs.
030  *
031  * @package diff
032  */
033  class diff_renderer
034  {
035      /**
036      * Number of leading context "lines" to preserve.
037      *
038      * This should be left at zero for this class, but subclasses may want to
039      * set this to other values.
040      */
041      var $_leading_context_lines = 0;
042   
043      /**
044      * Number of trailing context "lines" to preserve.
045      *
046      * This should be left at zero for this class, but subclasses may want to
047      * set this to other values.
048      */
049      var $_trailing_context_lines = 0;
050   
051      /**
052      * Constructor.
053      */
054      function diff_renderer($params = array())
055      {
056          foreach ($params as $param => $value)
057          {
058              $v = '_' . $param;
059              if (isset($this->$v))
060              {
061                  $this->$v = $value;
062              }
063          }
064      }
065   
066      /**
067      * Get any renderer parameters.
068      *
069      * @return array  All parameters of this renderer object.
070      */
071      function get_params()
072      {
073          $params = array();
074          foreach (get_object_vars($this) as $k => $v)
075          {
076              if ($k[0] == '_')
077              {
078                  $params[substr($k, 1)] = $v;
079              }
080          }
081   
082          return $params;
083      }
084   
085      /**
086      * Renders a diff.
087      *
088      * @param diff &$diff A diff object.
089      *
090      * @return string  The formatted output.
091      */
092      function render(&$diff)
093      {
094          $xi = $yi = 1;
095          $block = false;
096          $context = array();
097   
098          // Create a new diff object if it is a 3-way diff
099          if (is_a($diff, 'diff3'))
100          {
101              $diff3 = &$diff;
102   
103              $diff_1 = $diff3->get_original();
104              $diff_2 = $diff3->merged_output();
105   
106              unset($diff3);
107   
108              $diff = &new diff($diff_1, $diff_2);
109          }
110   
111          $nlead = $this->_leading_context_lines;
112          $ntrail = $this->_trailing_context_lines;
113   
114          $output = $this->_start_diff();
115          $diffs = $diff->get_diff();
116   
117          foreach ($diffs as $i => $edit)
118          {
119              if (is_a($edit, 'diff_op_copy'))
120              {
121                  if (is_array($block))
122                  {
123                      $keep = ($i == sizeof($diffs) - 1) ? $ntrail : $nlead + $ntrail;
124                      if (sizeof($edit->orig) <= $keep)
125                      {
126                          $block[] = $edit;
127                      }
128                      else
129                      {
130                          if ($ntrail)
131                          {
132                              $context = array_slice($edit->orig, 0, $ntrail);
133                              $block[] = &new diff_op_copy($context);
134                          }
135   
136                          $output .= $this->_block($x0, $ntrail + $xi - $x0, $y0, $ntrail + $yi - $y0, $block);
137                          $block = false;
138                      }
139                  }
140                  $context = $edit->orig;
141              }
142              else
143              {
144                  if (!is_array($block))
145                  {
146                      $context = array_slice($context, sizeof($context) - $nlead);
147                      $x0 = $xi - sizeof($context);
148                      $y0 = $yi - sizeof($context);
149                      $block = array();
150   
151                      if ($context)
152                      {
153                          $block[] = &new diff_op_copy($context);
154                      }
155                  }
156                  $block[] = $edit;
157              }
158   
159              $xi += ($edit->orig) ? sizeof($edit->orig) : 0;
160              $yi += ($edit->final) ? sizeof($edit->final) : 0;
161          }
162   
163          if (is_array($block))
164          {
165              $output .= $this->_block($x0, $xi - $x0, $y0, $yi - $y0, $block);
166          }
167   
168          return $output . $this->_end_diff();
169      }
170   
171      function _block($xbeg, $xlen, $ybeg, $ylen, &$edits)
172      {
173          $output = $this->_start_block($this->_block_header($xbeg, $xlen, $ybeg, $ylen));
174   
175          foreach ($edits as $edit)
176          {
177              switch (get_class($edit))
178              {
179                  case 'diff_op_copy':
180                      $output .= $this->_context($edit->orig);
181                  break;
182   
183                  case 'diff_op_add':
184                      $output .= $this->_added($edit->final);
185                  break;
186   
187                  case 'diff_op_delete':
188                      $output .= $this->_deleted($edit->orig);
189                  break;
190   
191                  case 'diff_op_change':
192                      $output .= $this->_changed($edit->orig, $edit->final);
193                  break;
194              }
195          }
196   
197          return $output . $this->_end_block();
198      }
199   
200      function _start_diff()
201      {
202          return '';
203      }
204   
205      function _end_diff()
206      {
207          return '';
208      }
209   
210      function _block_header($xbeg, $xlen, $ybeg, $ylen)
211      {
212          if ($xlen > 1)
213          {
214              $xbeg .= ',' . ($xbeg + $xlen - 1);
215          }
216   
217          if ($ylen > 1)
218          {
219              $ybeg .= ',' . ($ybeg + $ylen - 1);
220          }
221   
222          return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
223      }
224   
225      function _start_block($header)
226      {
227          return $header . "\n";
228      }
229   
230      function _end_block()
231      {
232          return '';
233      }
234   
235      function _lines($lines, $prefix = ' ')
236      {
237          return $prefix . implode("\n$prefix", $lines) . "\n";
238      }
239   
240      function _context($lines)
241      {
242          return $this->_lines($lines, '  ');
243      }
244   
245      function _added($lines)
246      {
247          return $this->_lines($lines, '> ');
248      }
249   
250      function _deleted($lines)
251      {
252          return $this->_lines($lines, '< ');
253      }
254   
255      function _changed($orig, $final)
256      {
257          return $this->_deleted($orig) . "---\n" . $this->_added($final);
258      }
259   
260      /**
261      * Our function to get the diff
262      */
263      function get_diff_content($diff)
264      {
265          return $this->render($diff);
266      }
267  }
268   
269  /**
270  * Renders a unified diff
271  * @package diff
272  */
273  class diff_renderer_unified extends diff_renderer
274  {
275      var $_leading_context_lines = 4;
276      var $_trailing_context_lines = 4;
277   
278      /**
279      * Our function to get the diff
280      */
281      function get_diff_content($diff)
282      {
283          return nl2br($this->render($diff));
284      }
285   
286      function _block_header($xbeg, $xlen, $ybeg, $ylen)
287      {
288          if ($xlen != 1)
289          {
290              $xbeg .= ',' . $xlen;
291          }
292   
293          if ($ylen != 1)
294          {
295              $ybeg .= ',' . $ylen;
296          }
297          return '<div class="diff"><big class="info">@@ -' . $xbeg . ' +' . $ybeg . ' @@</big></div>';
298      }
299   
300      function _context($lines)
301      {
302          return '<pre class="diff context">' . htmlspecialchars($this->_lines($lines, ' ')) . '<br /></pre>';
303      }
304      
305      function _added($lines)
306      {
307          return '<pre class="diff added">' . htmlspecialchars($this->_lines($lines, '+')) . '<br /></pre>';
308      }
309   
310      function _deleted($lines)
311      {
312          return '<pre class="diff removed">' . htmlspecialchars($this->_lines($lines, '-')) . '<br /></pre>';
313      }
314   
315      function _changed($orig, $final)
316      {
317          return $this->_deleted($orig) . $this->_added($final);
318      }
319   
320      function _start_diff()
321      {
322          $start = '<div class="file">';
323   
324          return $start;
325      }
326   
327      function _end_diff()
328      {
329          return '</div>';
330      }
331   
332      function _end_block()
333      {
334          return '';
335      }
336  }
337   
338  /**
339  * "Inline" diff renderer.
340  *
341  * This class renders diffs in the Wiki-style "inline" format.
342  *
343  * @author  Ciprian Popovici
344  * @package diff
345  */
346  class diff_renderer_inline extends diff_renderer
347  {
348      var $_leading_context_lines = 10000;
349      var $_trailing_context_lines = 10000;
350   
351      // Prefix and suffix for inserted text
352      var $_ins_prefix = '<span class="ins">';
353      var $_ins_suffix = '</span>';
354   
355      // Prefix and suffix for deleted text
356      var $_del_prefix = '<span class="del">';
357      var $_del_suffix = '</span>';
358   
359      var $_block_head = '';
360   
361      // What are we currently splitting on? Used to recurse to show word-level
362      var $_split_level = 'lines';
363   
364      /**
365      * Our function to get the diff
366      */
367      function get_diff_content($diff)
368      {
369          return '<pre>' . nl2br($this->render($diff)) . '<br /></pre>';
370      }
371   
372      function _start_diff()
373      {
374          return '';
375      }
376   
377      function _end_diff()
378      {
379          return '';
380      }
381   
382      function _block_header($xbeg, $xlen, $ybeg, $ylen)
383      {
384          return $this->_block_head;
385      }
386   
387      function _start_block($header)
388      {
389          return $header;
390      }
391   
392      function _lines($lines, $prefix = ' ', $encode = true)
393      {
394          if ($encode)
395          {
396              array_walk($lines, array(&$this, '_encode'));
397          }
398   
399          if ($this->_split_level == 'words')
400          {
401              return implode('', $lines);
402          }
403          else
404          {
405              return implode("\n", $lines) . "\n";
406          }
407      }
408   
409      function _added($lines)
410      {
411          array_walk($lines, array(&$this, '_encode'));
412          $lines[0] = $this->_ins_prefix . $lines[0];
413          $lines[sizeof($lines) - 1] .= $this->_ins_suffix;
414          return $this->_lines($lines, ' ', false);
415      }
416   
417      function _deleted($lines, $words = false)
418      {
419          array_walk($lines, array(&$this, '_encode'));
420          $lines[0] = $this->_del_prefix . $lines[0];
421          $lines[sizeof($lines) - 1] .= $this->_del_suffix;
422          return $this->_lines($lines, ' ', false);
423      }
424   
425      function _changed($orig, $final)
426      {
427          // If we've already split on words, don't try to do so again - just display.
428          if ($this->_split_level == 'words')
429          {
430              $prefix = '';
431              while ($orig[0] !== false && $final[0] !== false && substr($orig[0], 0, 1) == ' ' && substr($final[0], 0, 1) == ' ')
432              {
433                  $prefix .= substr($orig[0], 0, 1);
434                  $orig[0] = substr($orig[0], 1);
435                  $final[0] = substr($final[0], 1);
436              }
437   
438              return $prefix . $this->_deleted($orig) . $this->_added($final);
439          }
440   
441          $text1 = implode("\n", $orig);
442          $text2 = implode("\n", $final);
443   
444          // Non-printing newline marker.
445          $nl = "\0";
446   
447          // We want to split on word boundaries, but we need to preserve whitespace as well.
448          // Therefore we split on words, but include all blocks of whitespace in the wordlist.
449          $splitted_text_1 = $this->_split_on_words($text1, $nl);
450          $splitted_text_2 = $this->_split_on_words($text2, $nl);
451          
452          $diff = &new diff($splitted_text_1, $splitted_text_2);
453          unset($splitted_text_1, $splitted_text_2);
454   
455          // Get the diff in inline format.
456          $renderer = &new diff_renderer_inline(array_merge($this->get_params(), array('split_level' => 'words')));
457   
458          // Run the diff and get the output.
459          return str_replace($nl, "\n", $renderer->render($diff)) . "\n";
460      }
461   
462      function _split_on_words($string, $newline_escape = "\n")
463      {
464          // Ignore \0; otherwise the while loop will never finish.
465          $string = str_replace("\0", '', $string);
466          
467          $words = array();
468          $length = strlen($string);
469          $pos = 0;
470   
471          $tab_there = true;
472          while ($pos < $length)
473          {
474              // Check for tabs... do not include them
475              if ($tab_there && substr($string, $pos, 1) === "\t")
476              {
477                  $words[] = "\t";
478                  $pos++;
479   
480                  continue;
481              }
482              else
483              {
484                  $tab_there = false;
485              }
486   
487              // Eat a word with any preceding whitespace.
488              $spaces = strspn(substr($string, $pos), " \n");
489              $nextpos = strcspn(substr($string, $pos + $spaces), " \n");
490              $words[] = str_replace("\n", $newline_escape, substr($string, $pos, $spaces + $nextpos));
491              $pos += $spaces + $nextpos;
492          }
493   
494          return $words;
495      }
496   
497      function _encode(&$string)
498      {
499          $string = htmlspecialchars($string);
500      }
501  }
502   
503  /**
504  * "raw" diff renderer.
505  * This class could be used to output a raw unified patch file
506  *
507  * @package diff
508  */
509  class diff_renderer_raw extends diff_renderer
510  {
511      var $_leading_context_lines = 4;
512      var $_trailing_context_lines = 4;
513   
514      /**
515      * Our function to get the diff
516      */
517      function get_diff_content($diff)
518      {
519          return '<textarea style="height: 290px;" class="full">' . htmlspecialchars($this->render($diff)) . '</textarea>';
520      }
521   
522      function _block_header($xbeg, $xlen, $ybeg, $ylen)
523      {
524          if ($xlen != 1)
525          {
526              $xbeg .= ',' . $xlen;
527          }
528   
529          if ($ylen != 1)
530          {
531              $ybeg .= ',' . $ylen;
532          }
533          return '@@ -' . $xbeg . ' +' . $ybeg . ' @@';
534      }
535   
536      function _context($lines)
537      {
538          return $this->_lines($lines, ' ');
539      }
540      
541      function _added($lines)
542      {
543          return $this->_lines($lines, '+');
544      }
545   
546      function _deleted($lines)
547      {
548          return $this->_lines($lines, '-');
549      }
550   
551      function _changed($orig, $final)
552      {
553          return $this->_deleted($orig) . $this->_added($final);
554      }
555  }
556   
557  /**
558  * "chora (Horde)" diff renderer - similar style.
559  * This renderer class is a modified human_readable function from the Horde Framework.
560  *
561  * @package diff
562  */
563  class diff_renderer_side_by_side extends diff_renderer
564  {
565      var $_leading_context_lines = 3;
566      var $_trailing_context_lines = 3;
567   
568      var $lines = array();
569   
570      // Hold the left and right columns of lines for change blocks.
571      var $cols;
572      var $state;
573   
574      var $data = false;
575   
576      /**
577      * Our function to get the diff
578      */
579      function get_diff_content($diff)
580      {
581          global $user;
582   
583          $output = '';
584          $output .= '<table cellspacing="0" class="hrdiff">
585  <caption>
586      <span class="unmodified">&nbsp;</span> ' . $user->lang['LINE_UNMODIFIED'] . '
587      <span class="added">&nbsp;</span> ' . $user->lang['LINE_ADDED'] . '
588      <span class="modified">&nbsp;</span> ' . $user->lang['LINE_MODIFIED'] . '
589      <span class="removed">&nbsp;</span> ' . $user->lang['LINE_REMOVED'] . '
590  </caption>
591  <tbody>
592  ';
593   
594          $this->render($diff);
595   
596          // Is the diff empty?
597          if (!sizeof($this->lines))
598          {
599              $output .= '<tr><th colspan="2">' . $user->lang['NO_VISIBLE_CHANGES'] . '</th></tr>';
600          }
601          else
602          {
603              // Iterate through every header block of changes
604              foreach ($this->lines as $header)
605              {
606                  $output .= '<tr><th>Line ' . $header['oldline'] . '</th><th>' . $user->lang['LINE'] . ' ' . $header['newline'] . '</th></tr>';
607   
608                  // Each header block consists of a number of changes (add, remove, change).
609                  $current_context = '';
610   
611                  foreach ($header['contents'] as $change)
612                  {
613                      if (!empty($current_context) && $change['type'] != 'empty')
614                      {
615                          $line = $current_context;
616                          $current_context = '';
617   
618                          $output .= '<tr class="unmodified"><td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td>
619                              <td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td></tr>';
620                      }
621   
622                      switch ($change['type'])
623                      {
624                          case 'add':
625                              $line = '';
626   
627                              foreach ($change['lines'] as $_line)
628                              {
629                                  $line .= htmlspecialchars($_line) . '<br />';
630                              }
631   
632                              $output .= '<tr><td class="added_empty">&nbsp;</td><td class="added"><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td></tr>';
633                          break;
634   
635                          case 'remove':
636                              $line = '';
637   
638                              foreach ($change['lines'] as $_line)
639                              {
640                                  $line .= htmlspecialchars($_line) . '<br />';
641                              }
642   
643                              $output .= '<tr><td class="removed"><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td><td class="removed_empty">&nbsp;</td></tr>';
644                          break;
645   
646                          case 'empty':
647                              $current_context .= htmlspecialchars($change['line']) . '<br />';
648                          break;
649   
650                          case 'change':
651                              // Pop the old/new stacks one by one, until both are empty.
652                              $oldsize = sizeof($change['old']);
653                              $newsize = sizeof($change['new']);
654                              $left = $right = '';
655   
656                              for ($row = 0, $row_max = max($oldsize, $newsize); $row < $row_max; ++$row)
657                              {
658                                  $left .= isset($change['old'][$row]) ? htmlspecialchars($change['old'][$row]) : '';
659                                  $left .= '<br />';
660                                  $right .= isset($change['new'][$row]) ? htmlspecialchars($change['new'][$row]) : '';
661                                  $right .= '<br />';
662                              }
663   
664                              $output .= '<tr>';
665   
666                              if (!empty($left))
667                              {
668                                  $output .= '<td class="modified"><pre>' . $left . '<br /></pre></td>';
669                              }
670                              else if ($row < $oldsize)
671                              {
672                                  $output .= '<td class="modified">&nbsp;</td>';
673                              }
674                              else
675                              {
676                                  $output .= '<td class="unmodified">&nbsp;</td>';
677                              }
678   
679                              if (!empty($right))
680                              {
681                                  $output .= '<td class="modified"><pre>' . $right . '<br /></pre></td>';
682                              }
683                              else if ($row < $newsize)
684                              {
685                                  $output .= '<td class="modified">&nbsp;</td>';
686                              }
687                              else
688                              {
689                                  $output .= '<td class="unmodified">&nbsp;</td>';
690                              }
691   
692                              $output .= '</tr>';
693                          break;
694                      }
695                  }
696   
697                  if (!empty($current_context))
698                  {
699                      $line = $current_context;
700                      $current_context = '';
701   
702                      $output .= '<tr class="unmodified"><td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td>';
703                      $output .= '<td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td></tr>';
704                  }
705              }
706          }
707   
708          $output .= '</tbody></table>';
709   
710          return $output;
711      }
712   
713      function _start_diff()
714      {
715          $this->lines = array();
716   
717          $this->data = false;
718          $this->cols = array(array(), array());
719          $this->state = 'empty';
720   
721          return '';
722      }
723   
724      function _end_diff()
725      {
726          // Just flush any remaining entries in the columns stack.
727          switch ($this->state)
728          {
729              case 'add':
730                  $this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]);
731              break;
732   
733              case 'remove':
734                  // We have some removal lines pending in our stack, so flush them.
735                  $this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]);
736              break;
737   
738              case 'change':
739                  // We have both remove and addition lines, so this is a change block.
740                  $this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]);
741              break;
742          }
743   
744          if ($this->data !== false)
745          {
746              $this->lines[] = $this->data;
747          }
748   
749          return '';
750      }
751   
752      function _block_header($xbeg, $xlen, $ybeg, $ylen)
753      {
754          // Push any previous header information to the return stack.
755          if ($this->data !== false)
756          {
757              $this->lines[] = $this->data;
758          }
759   
760          $this->data = array('type' => 'header', 'oldline' => $xbeg, 'newline' => $ybeg, 'contents' => array());
761          $this->state = 'dump';
762      }
763   
764      function _added($lines)
765      {
766          array_walk($lines, array(&$this, '_perform_add'));
767      }
768   
769      function _perform_add($line)
770      {
771          if ($this->state == 'empty')
772          {
773              return '';
774          }
775   
776          // This is just an addition line.
777          if ($this->state == 'dump' || $this->state == 'add')
778          {
779              // Start adding to the addition stack.
780              $this->cols[0][] = $line;
781              $this->state = 'add';
782          }
783          else
784          {
785              // This is inside a change block, so start accumulating lines.
786              $this->state = 'change';
787              $this->cols[1][] = $line;
788          }
789      }
790   
791      function _deleted($lines)
792      {
793          array_walk($lines, array(&$this, '_perform_delete'));
794      }
795   
796      function _perform_delete($line)
797      {
798          // This is a removal line.
799          $this->state = 'remove';
800          $this->cols[0][] = $line;
801      }
802   
803      function _context($lines)
804      {
805          array_walk($lines, array(&$this, '_perform_context'));
806      }
807   
808      function _perform_context($line)
809      {
810          // An empty block with no action.
811          switch ($this->state)
812          {
813              case 'add':
814                  $this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]);
815              break;
816   
817              case 'remove':
818                  // We have some removal lines pending in our stack, so flush them.
819                  $this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]);
820              break;
821   
822              case 'change':
823                  // We have both remove and addition lines, so this is a change block.
824                  $this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]);
825              break;
826          }
827   
828          $this->cols = array(array(), array());
829          $this->data['contents'][] = array('type' => 'empty', 'line' => $line);
830          $this->state = 'dump';
831      }
832   
833      function _changed($orig, $final)
834      {
835          return $this->_deleted($orig) . $this->_added($final);
836      }
837   
838  }
839   
840  ?>