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