PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-includes/Text/Diff/Renderer/inline.php

https://bitbucket.org/geetharani/gordon
PHP | 206 lines | 98 code | 31 blank | 77 comment | 15 complexity | 880ae56e35b150b4b2c7e9d94227e81e MD5 | raw file
Possible License(s): MIT
  1. <?php
  2. /**
  3. * "Inline" diff renderer.
  4. *
  5. * Copyright 2004-2010 The Horde Project (http://www.horde.org/)
  6. *
  7. * See the enclosed file COPYING for license information (LGPL). If you did
  8. * not receive this file, see http://opensource.org/licenses/lgpl-license.php.
  9. *
  10. * @author Ciprian Popovici
  11. * @package Text_Diff
  12. */
  13. /** Text_Diff_Renderer */
  14. // WP #7391
  15. require_once dirname(dirname(__FILE__)) . '/Renderer.php';
  16. /**
  17. * "Inline" diff renderer.
  18. *
  19. * This class renders diffs in the Wiki-style "inline" format.
  20. *
  21. * @author Ciprian Popovici
  22. * @package Text_Diff
  23. */
  24. class Text_Diff_Renderer_inline extends Text_Diff_Renderer {
  25. /**
  26. * Number of leading context "lines" to preserve.
  27. *
  28. * @var integer
  29. */
  30. var $_leading_context_lines = 10000;
  31. /**
  32. * Number of trailing context "lines" to preserve.
  33. *
  34. * @var integer
  35. */
  36. var $_trailing_context_lines = 10000;
  37. /**
  38. * Prefix for inserted text.
  39. *
  40. * @var string
  41. */
  42. var $_ins_prefix = '<ins>';
  43. /**
  44. * Suffix for inserted text.
  45. *
  46. * @var string
  47. */
  48. var $_ins_suffix = '</ins>';
  49. /**
  50. * Prefix for deleted text.
  51. *
  52. * @var string
  53. */
  54. var $_del_prefix = '<del>';
  55. /**
  56. * Suffix for deleted text.
  57. *
  58. * @var string
  59. */
  60. var $_del_suffix = '</del>';
  61. /**
  62. * Header for each change block.
  63. *
  64. * @var string
  65. */
  66. var $_block_header = '';
  67. /**
  68. * Whether to split down to character-level.
  69. *
  70. * @var boolean
  71. */
  72. var $_split_characters = false;
  73. /**
  74. * What are we currently splitting on? Used to recurse to show word-level
  75. * or character-level changes.
  76. *
  77. * @var string
  78. */
  79. var $_split_level = 'lines';
  80. function _blockHeader($xbeg, $xlen, $ybeg, $ylen)
  81. {
  82. return $this->_block_header;
  83. }
  84. function _startBlock($header)
  85. {
  86. return $header;
  87. }
  88. function _lines($lines, $prefix = ' ', $encode = true)
  89. {
  90. if ($encode) {
  91. array_walk($lines, array(&$this, '_encode'));
  92. }
  93. if ($this->_split_level == 'lines') {
  94. return implode("\n", $lines) . "\n";
  95. } else {
  96. return implode('', $lines);
  97. }
  98. }
  99. function _added($lines)
  100. {
  101. array_walk($lines, array(&$this, '_encode'));
  102. $lines[0] = $this->_ins_prefix . $lines[0];
  103. $lines[count($lines) - 1] .= $this->_ins_suffix;
  104. return $this->_lines($lines, ' ', false);
  105. }
  106. function _deleted($lines, $words = false)
  107. {
  108. array_walk($lines, array(&$this, '_encode'));
  109. $lines[0] = $this->_del_prefix . $lines[0];
  110. $lines[count($lines) - 1] .= $this->_del_suffix;
  111. return $this->_lines($lines, ' ', false);
  112. }
  113. function _changed($orig, $final)
  114. {
  115. /* If we've already split on characters, just display. */
  116. if ($this->_split_level == 'characters') {
  117. return $this->_deleted($orig)
  118. . $this->_added($final);
  119. }
  120. /* If we've already split on words, just display. */
  121. if ($this->_split_level == 'words') {
  122. $prefix = '';
  123. while ($orig[0] !== false && $final[0] !== false &&
  124. substr($orig[0], 0, 1) == ' ' &&
  125. substr($final[0], 0, 1) == ' ') {
  126. $prefix .= substr($orig[0], 0, 1);
  127. $orig[0] = substr($orig[0], 1);
  128. $final[0] = substr($final[0], 1);
  129. }
  130. return $prefix . $this->_deleted($orig) . $this->_added($final);
  131. }
  132. $text1 = implode("\n", $orig);
  133. $text2 = implode("\n", $final);
  134. /* Non-printing newline marker. */
  135. $nl = "\0";
  136. if ($this->_split_characters) {
  137. $diff = new Text_Diff('native',
  138. array(preg_split('//', $text1),
  139. preg_split('//', $text2)));
  140. } else {
  141. /* We want to split on word boundaries, but we need to preserve
  142. * whitespace as well. Therefore we split on words, but include
  143. * all blocks of whitespace in the wordlist. */
  144. $diff = new Text_Diff('native',
  145. array($this->_splitOnWords($text1, $nl),
  146. $this->_splitOnWords($text2, $nl)));
  147. }
  148. /* Get the diff in inline format. */
  149. $renderer = new Text_Diff_Renderer_inline
  150. (array_merge($this->getParams(),
  151. array('split_level' => $this->_split_characters ? 'characters' : 'words')));
  152. /* Run the diff and get the output. */
  153. return str_replace($nl, "\n", $renderer->render($diff)) . "\n";
  154. }
  155. function _splitOnWords($string, $newlineEscape = "\n")
  156. {
  157. // Ignore \0; otherwise the while loop will never finish.
  158. $string = str_replace("\0", '', $string);
  159. $words = array();
  160. $length = strlen($string);
  161. $pos = 0;
  162. while ($pos < $length) {
  163. // Eat a word with any preceding whitespace.
  164. $spaces = strspn(substr($string, $pos), " \n");
  165. $nextpos = strcspn(substr($string, $pos + $spaces), " \n");
  166. $words[] = str_replace("\n", $newlineEscape, substr($string, $pos, $spaces + $nextpos));
  167. $pos += $spaces + $nextpos;
  168. }
  169. return $words;
  170. }
  171. function _encode(&$string)
  172. {
  173. $string = htmlspecialchars($string);
  174. }
  175. }