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

/src/system/application/libraries/Htmldiff.php

https://bitbucket.org/seezoo/seezoo/
PHP | 307 lines | 210 code | 31 blank | 66 comment | 60 complexity | 2dca030b4b0b9737a823d70433dc60af MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * Replacement of htmldiff.py
  4. *
  5. * Requirement:
  6. * PEAR::Text_Diff
  7. * OS diff command
  8. * shell_exec()
  9. *
  10. * @author Kenji Suzuki <kenji@club.h14m.org> Thanks!
  11. * @copyright Copyright (c) 2009 Kenji Suzuki
  12. * @modified at 2010/10/29 Yoshiaki Sugimoto <neo.yoshiaki.sugimoto@gmail.com>
  13. *
  14. */
  15. class Htmldiff
  16. {
  17. protected $past_version;
  18. protected $latest_version;
  19. public function __construct() {
  20. require_once APPPATH . 'libraries/HtmlDiff/Diff.php';
  21. require_once APPPATH . 'libraries/HtmlDiff/Diff/Renderer.php';
  22. require_once APPPATH . 'libraries/HtmlDiff/Diff/Renderer/unified.php';
  23. }
  24. /**
  25. * additional method getDiffFromFile
  26. * get diff from two files
  27. * @param unknown_type $file1
  28. * @param unknown_type $file2
  29. */
  30. public function getDiffFromFile($file1, $file2)
  31. {
  32. /* Make sure both files exist. */
  33. if (!is_readable($file1)) {
  34. return "$file1 not found or not readable.";
  35. }
  36. if (!is_readable($file2)) {
  37. return "$file2 not found or not readable.";
  38. }
  39. /* Load the lines of each file. */
  40. $lines1 = file($file1);
  41. $lines2 = file($file2);
  42. return $this->_getDiff($lines1, $lines2);
  43. }
  44. /**
  45. * additionalmethod getDiffFromString
  46. * get diff from outputed string daa
  47. * @param unknown_type $text1
  48. * @param unknown_type $text2
  49. */
  50. public function getDiffFromString($str1, $str2)
  51. {
  52. $str1 = explode("\n", $str1);
  53. $str2 = explode("\n", $str2);
  54. return $this->_getDiff($str1, $str2);
  55. }
  56. /**
  57. * alias to getDiff public method
  58. * @param unknown_type $text1
  59. * @param unknown_type $text2
  60. */
  61. public function getDiff($file1, $file2)
  62. {
  63. return $this->getDiffFromFile($file1, $file2);
  64. }
  65. /**
  66. * getDiff from URI parameter files
  67. * Enter description here ...
  68. * @param unknown_type $text1
  69. * @param unknown_type $text2
  70. */
  71. function getDiffFromURIs($uri1, $uri2)
  72. {
  73. /* Make sure both uris strict format. */
  74. if ( ! preg_match('/^http/', $uri1) )
  75. {
  76. return "$uri1 is illegal URI format.";
  77. }
  78. if ( ! preg_match('/^http/', $uri2) )
  79. {
  80. return "$uri2 is illegal URI format.";
  81. }
  82. $lines1 = @file($uri1);
  83. $lines2 = @file($uri2);
  84. if ( ! $lines1 )
  85. {
  86. return "$uri1 is not found.";
  87. }
  88. if ( ! $lines2 )
  89. {
  90. return "$uri2 is not found.";
  91. }
  92. return $this->_getDiff($lines1, $lines2);
  93. }
  94. protected function _getDiff($text1, $text2) {
  95. // this process move to "getDiffFromFile" method.
  96. ///* Make sure both files exist. */
  97. //if (!is_readable($file1)) {
  98. // return "$file1 not found or not readable.";
  99. //}
  100. //if (!is_readable($file2)) {
  101. // return "$file2 not found or not readable.";
  102. //}
  103. //
  104. ///* Load the lines of each file. */
  105. //$lines1 = file($file1);
  106. //$lines2 = file($file2);
  107. $lines1 = $this->normailze($text1);
  108. $lines2 = $this->normailze($text2);
  109. /* Create the Diff object. */
  110. // 'shell' means to use diff command, we select it because it's smarter than 'native' PHP diff engine.
  111. $diff = new Text_Diff('auto', array($lines1, $lines2));
  112. /* Get the Diff result */
  113. $diffResult = $diff->getDiff();
  114. $version_txt = 'バージョン' . $this->past_version . '&nbsp;→&nbsp;' . $this->latest_version . '&nbsp;';
  115. $out = '';
  116. foreach ($diffResult as $index => $op) {
  117. if ($op instanceof Text_Diff_Op_copy) {
  118. // equal
  119. // orig is equl to final
  120. foreach ($op->orig as $line) {
  121. $out .= $line . PHP_EOL;
  122. }
  123. } else if ($op instanceof Text_Diff_Op_add) {
  124. // insert
  125. // orig is empty, final has content
  126. $out .= '<div class="diff" style="background-color:#87e7a2">';
  127. $out .= '<p style="text-align:left;font-size:12px">' . $version_txt . 'で追加</p>';
  128. foreach ($op->final as $line) {
  129. $out .= $line . PHP_EOL;
  130. }
  131. $out .= '</div>';
  132. } else if ($op instanceof Text_Diff_Op_delete) {
  133. // delete
  134. // orig has content, final is empty
  135. $out .= '<div class="diff" style="background-color:#ed9492">';
  136. $out .= '<p style="text-align:left;font-size:12px">' . $version_txt . 'で削除</p>';
  137. foreach ($op->orig as $line) {
  138. $out .= $line . PHP_EOL;
  139. }
  140. $out .= '</div>';
  141. } else if ($op instanceof Text_Diff_Op_change) {
  142. // replace
  143. $orig = array();
  144. foreach ($op->orig as $line) {
  145. $len = mb_strlen($line);
  146. if ($len > 0 && $line[0] == '<') {
  147. $orig[] = $line;
  148. } else {
  149. for ($i = 0; $i < $len; $i++) {
  150. $orig[] = mb_substr($line, $i, 1);
  151. }
  152. $orig[] = PHP_EOL;
  153. }
  154. }
  155. $final = array();
  156. foreach ($op->final as $line) {
  157. $len = mb_strlen($line);
  158. if ($len > 0 && $line[0] == '<') {
  159. $orig[] = $line;
  160. } else {
  161. for ($i = 0; $i < $len; $i++) {
  162. $final[] = mb_substr($line, $i, 1);
  163. }
  164. $final[] = PHP_EOL;
  165. }
  166. }
  167. $diffInChange = new Text_Diff('auto', array($orig, $final));
  168. $diffInChangeResult = $diffInChange->getDiff();
  169. foreach ($diffInChangeResult as $indexInChange => $opInChange) {
  170. if ($opInChange instanceof Text_Diff_Op_copy) {
  171. // equal
  172. foreach ($opInChange->orig as $line) {
  173. if ($line == '') {
  174. $line = PHP_EOL;
  175. }
  176. $out .= $line;
  177. }
  178. } else if ($opInChange instanceof Text_Diff_Op_add) {
  179. // insert
  180. $out .= '<div class="diff" style="background-color:#87e7a2">';
  181. $out .= '<p style="text-align:left;font-size:12px">' . $version_txt . 'で追加</p>';
  182. foreach ($opInChange->final as $line) {
  183. if ($line == '') {
  184. $line = PHP_EOL;
  185. }
  186. $out .= $line;
  187. }
  188. $out .= '</div>';
  189. } else if ($opInChange instanceof Text_Diff_Op_delete) {
  190. // delete
  191. $out .= '<div class="diff" style="backgorund-color:#ed9492">';
  192. $out .= '<p style="text-align:left;font-size:12px">' . $version_txt . 'で削除</p>';
  193. foreach ($opInChange->orig as $line) {
  194. if ($line == '') {
  195. $line = PHP_EOL;
  196. }
  197. $out .= $line;
  198. }
  199. $out .= '</del>';
  200. } else if ($op instanceof Text_Diff_Op_change) {
  201. // replace
  202. $out .= '<div class="diff modified" style="background-color:#ccc">';
  203. $out .= '<p style="text-align:left;font-size:12px">' . $version_txt . 'で削除</p>';
  204. foreach ($opInChange->orig as $line) {
  205. if ($line == '') {
  206. $line = PHP_EOL;
  207. }
  208. $out .= $line;
  209. }
  210. $out .= '</div><div class="diff modified" style="background-color:#00084c4"><p style="text-align:left;font-size:12px">' . $version_txt . 'で追加</p>';;
  211. foreach ($opInChange->final as $line) {
  212. if ($line == '') {
  213. $line = PHP_EOL;
  214. }
  215. $out .= $line;
  216. }
  217. $out .= '</div>';
  218. } else {
  219. printf("WARNING: unknown operation\n");
  220. }
  221. }
  222. } else {
  223. printf("WARNING: unknown operation\n");
  224. }
  225. }
  226. return $out;
  227. }
  228. private function normailze($lines) {
  229. $mode = 'char';
  230. $out = array();
  231. foreach ($lines as $line) {
  232. $len = strlen($line);
  233. for ($i = 0; $i < $len; $i++) {
  234. $c = $line[$i];
  235. if ($mode == 'tag') {
  236. if ($c == '>') {
  237. $tmp = array_pop($out);
  238. $out[] = $tmp . $c;
  239. $out[] = '';
  240. $mode = 'char';
  241. } else {
  242. $tmp = array_pop($out);
  243. $out[] = $tmp . $c;
  244. }
  245. }
  246. else if ($mode == 'char') {
  247. if ($c == '<') {
  248. $out[] = $c;
  249. $mode = 'tag';
  250. } else {
  251. if ($c != PHP_EOL) {
  252. $tmp = array_pop($out);
  253. } else {
  254. $tmp = '';
  255. }
  256. $out[] = $tmp . $c;
  257. }
  258. }
  259. }
  260. }
  261. $html = array();
  262. foreach ($out as $line) {
  263. $line = trim($line);
  264. if ($line != '') {
  265. $html[] = $line . PHP_EOL;
  266. }
  267. }
  268. return $html;
  269. }
  270. // version ID setter
  271. public function set_versions($past = 0, $latest = 0)
  272. {
  273. $this->past_version = $past;
  274. $this->latest_version = $latest;
  275. }
  276. }