~azzar1/unity/add-show-desktop-key

443 by dcoles
Added Forum application along with unmodifed version of phpBB3 "Olympus" 3.0.0
1
<?php
2
/**
3
*
4
* @package diff
5
* @version $Id: diff.php,v 1.8 2007/10/05 14:36:33 acydburn Exp $
6
* @copyright (c) 2006 phpBB Group
7
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
8
*
9
*/
10
11
/**
12
* @ignore
13
*/
14
if (!defined('IN_PHPBB'))
15
{
16
	exit;
17
}
18
19
/**
20
* Code from pear.php.net, Text_Diff-0.2.1 (beta) package
21
* http://pear.php.net/package/Text_Diff/
22
*
23
* Modified by phpBB Group to meet our coding standards
24
* and being able to integrate into phpBB
25
*
26
* General API for generating and formatting diffs - the differences between
27
* two sequences of strings.
28
*
29
* @package diff
30
* @author  Geoffrey T. Dairiki <dairiki@dairiki.org>
31
*/
32
class diff
33
{
34
	/**
35
	* Array of changes.
36
	* @var array
37
	*/
38
	var $_edits;
39
40
	/**
41
	* Computes diffs between sequences of strings.
42
	*
43
	* @param array $from_lines  An array of strings. Typically these are lines from a file.
44
	* @param array $to_lines    An array of strings.
45
	*/
46
	function diff(&$from_content, &$to_content, $preserve_cr = true)
47
	{
48
		$diff_engine = &new diff_engine();
49
		$this->_edits = $diff_engine->diff($from_content, $to_content, $preserve_cr);
50
	}
51
52
	/**
53
	* Returns the array of differences.
54
	*/
55
	function get_diff()
56
	{
57
		return $this->_edits;
58
	}
59
60
	/**
61
	* Computes a reversed diff.
62
	*
63
	* Example:
64
	* <code>
65
	* $diff = &new diff($lines1, $lines2);
66
	* $rev = $diff->reverse();
67
	* </code>
68
	*
69
	* @return diff  A Diff object representing the inverse of the original diff.
70
	*               Note that we purposely don't return a reference here, since
71
	*               this essentially is a clone() method.
72
	*/
73
	function reverse()
74
	{
75
		if (version_compare(zend_version(), '2', '>'))
76
		{
77
			$rev = clone($this);
78
		}
79
		else
80
		{
81
			$rev = $this;
82
		}
83
84
		$rev->_edits = array();
85
86
		foreach ($this->_edits as $edit)
87
		{
88
			$rev->_edits[] = $edit->reverse();
89
		}
90
91
		return $rev;
92
	}
93
94
	/**
95
	* Checks for an empty diff.
96
	*
97
	* @return boolean  True if two sequences were identical.
98
	*/
99
	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
?>