OSDN Git Service

b9aadfcb6a40e736a0965879c2a97101bd3b8116
[fswiki/fswiki.git] / plugin / core / Diff.pm
1 ###############################################################################
2
3 # º¹Ê¬¤òɽ¼¨¤¹¤ë¥×¥é¥°¥¤¥ó
4
5 ###############################################################################
6 package plugin::core::Diff;
7 use Algorithm::Diff qw(traverse_sequences);
8 use strict;
9
10 #==============================================================================
11 # ¥³¥ó¥¹¥È¥é¥¯¥¿
12 #==============================================================================
13 sub new {
14         my $class = shift;
15         my $self = {};
16         
17         return bless $self,$class;
18 }
19
20 #==============================================================================
21 # ¥¢¥¯¥·¥ç¥ó¤Î¼Â¹Ô
22 #==============================================================================
23 sub do_action {
24         my $self = shift;
25         my $wiki = shift;
26         my $cgi = $wiki->get_CGI;
27         
28         my $pagename = $cgi->param("page");
29         if($pagename eq ""){
30                 $pagename = $wiki->config("frontpage");
31         }
32         unless($wiki->can_show($pagename)){
33                 return $wiki->error("»²¾È¸¢¸Â¤¬¤¢¤ê¤Þ¤»¤ó¡£");
34         }
35         if($cgi->param('rollback') ne ''){
36                 return $self->rollback($wiki, $pagename, $cgi->param('rollback'));
37         } elsif($wiki->{storage}->backup_type eq 'all'){
38                 if($cgi->param('generation') eq '' && $cgi->param('diff') eq ''){
39                         return $self->show_history($wiki, $pagename);
40                 } else {
41                         if($cgi->param('generation') ne ''){
42                                 return $self->show_diff($wiki, $pagename, '', $cgi->param('generation'));
43                         }
44                         return $self->show_diff($wiki, $pagename, $cgi->param('from'), $cgi->param('to'));
45                 }
46         } else {
47                 return $self->show_diff($wiki, $pagename, 0);
48         }
49 }
50
51 #==============================================================================
52 # ÍúÎò¤«¤é¥Ú¡¼¥¸¤òÉü¸µ
53 #==============================================================================
54 sub rollback {
55         my $self = shift;
56         my $wiki = shift;
57         my $page = shift;
58         my $gen  = shift;
59         unless($wiki->can_modify_page($page)){
60                 return $wiki->error("¹¹¿·¸¢¸Â¤¬¤¢¤ê¤Þ¤»¤ó¡£");
61         }
62         my $source = $wiki->get_backup($page,$gen);
63         $wiki->save_page($page, $source);
64         return $wiki->redirect($page);
65 }
66
67 #==============================================================================
68 # ÍúÎò¤Î°ìÍ÷¤òɽ¼¨
69 # ¥¹¥È¥ì¡¼¥¸¤Îbackup_type=all¤Î¤È¤­
70 #==============================================================================
71 sub show_history {
72         my $self = shift;
73         my $wiki = shift;
74         my $pagename = shift;
75         
76         $wiki->set_title($pagename."¤ÎÊѹ¹ÍúÎò");
77         my $buf   = "<form><ul>\n";
78         my $count = 0;
79         my @list  = $wiki->{storage}->get_backup_list($pagename);
80         
81         if($#list == -1){
82                 return "ÍúÎò¤Ï¤¢¤ê¤Þ¤»¤ó¡£";
83         }
84         
85         foreach my $time (@list){
86                 $buf .= "<li>";
87                 if($count == 0){
88                         $buf .= "<input type=\"radio\" name=\"from\" value=\"\" checked>".
89                                 "<input type=\"radio\" name=\"to\" value=\"\" checked>";
90                 } else {
91                         $buf .= "<input type=\"radio\" name=\"from\" value=\"".($#list-$count+1)."\">".
92                                 "<input type=\"radio\" name=\"to\" value=\"".($#list-$count+1)."\">";
93                 }
94                 $buf .= "<a href=\"".$wiki->create_url({ action=>"DIFF",page=>$pagename,generation=>($#list-$count) })."\">".&Util::escapeHTML($time).
95                         "</a>¡¡<a href=\"".$wiki->create_url({ action=>"SOURCE",page=>$pagename,generation=>($#list-$count) })."\">¥½¡¼¥¹</a>".
96                         "</li>\n";
97                 $count++;
98         }
99         return $buf."</ul>".
100         "<input type=\"hidden\" name=\"page\" value=\"".Util::escapeHTML($pagename)."\">".
101         "<input type=\"hidden\" name=\"action\" value=\"DIFF\">".
102         "<input type=\"submit\" name=\"diff\" value=\"ÁªÂò¤·¤¿¥ê¥Ó¥¸¥ç¥ó´Ö¤Îº¹Ê¬¤òɽ¼¨\"></form>\n";
103 }
104
105 #==============================================================================
106 # º¹Ê¬¤òɽ¼¨
107 #==============================================================================
108 sub show_diff {
109         my $self     = shift;
110         my $wiki     = shift;
111         my $pagename = shift;
112         my $from     = shift;
113         my $to       = shift;
114         
115         $wiki->set_title($pagename."¤ÎÊѹ¹ÅÀ");
116         my ($diff, $rollback) = $self->get_diff_html($wiki,$pagename, $from, $to);
117         
118         $diff =~ s/\n/<br>/g;
119         
120         my $buf = qq|
121                 <ul>
122                   <li>Äɲ䵤줿¹Ô¤Ï<ins class="diff">¤³¤Î¤è¤¦¤Ë</ins>ɽ¼¨¤µ¤ì¤Þ¤¹¡£</li>
123                   <li>ºï½ü¤µ¤ì¤¿¹Ô¤Ï<del class="diff">¤³¤Î¤è¤¦¤Ë</del>ɽ¼¨¤µ¤ì¤Þ¤¹¡£</li>
124                 </ul>
125                 <div class="diff">$diff</div>
126         |;
127         
128         if($wiki->can_modify_page($pagename) && $rollback && $wiki->get_CGI->param('diff') eq ''){
129                 $buf .= qq|
130                         <form action="@{[$wiki->create_url()]}" method="POST">
131                                 <input type="submit" value="¤³¤Î¥Ð¡¼¥¸¥ç¥ó¤ËÌ᤹"/>
132                                 <input type="hidden" name="action" value="DIFF"/>
133                                 <input type="hidden" name="page" value="@{[Util::escapeHTML($pagename)]}"/>
134                                 <input type="hidden" name="rollback" value="@{[Util::escapeHTML($from)]}"/>
135                         </form>
136                 |;
137         }
138         
139         return $buf;
140 }
141
142 #==============================================================================
143 # º¹Ê¬Ê¸»úÎó¤ò¼èÆÀ
144 #==============================================================================
145 sub get_diff_text {
146         my $self       = shift;
147         my $wiki       = shift;
148         my $pagename   = shift;
149         my $generation = shift;
150         
151         my $source1 = $wiki->get_page($pagename);
152         my $source2 = $wiki->get_backup($pagename,$generation);
153         my $format  = $wiki->get_edit_format();
154         
155         $source1 = $wiki->convert_from_fswiki($source1,$format);
156         $source2 = $wiki->convert_from_fswiki($source2,$format);
157         
158         my $diff_text = "";
159         my @msg1 = split(/\n/,$source1);
160         my @msg2 = split(/\n/,$source2);
161         my $msgrefA = \@msg2;
162         my $msgrefB = \@msg1;
163         
164         traverse_sequences($msgrefA, $msgrefB,
165                 {
166                         MATCH => sub {},
167                         DISCARD_A => sub {
168                                 my ($a, $b) = @_;
169                                 $diff_text .= "-".$msgrefA->[$a]."\n";
170                         },
171                         DISCARD_B => sub {
172                                 my ($a, $b) = @_;
173                                 $diff_text .= "+".$msgrefB->[$b]."\n";
174                         }
175                 });
176         
177         return $diff_text;
178 }
179
180 #==============================================================================
181 # º¹Ê¬Ê¸»úÎó¤òɽ¼¨ÍÑHTML¤È¤·¤Æ¼èÆÀ
182 #==============================================================================
183 sub get_diff_html {
184         my $self     = shift;
185         my $wiki     = shift;
186         my $pagename = shift;
187         my $from     = shift;
188         my $to       = shift;
189         
190         my $source1 = '';
191         if($from ne ''){
192                 $source1 = $wiki->get_backup($pagename, $from);
193         } else {
194                 $source1 = $wiki->get_page($pagename);
195         }
196         my $source2 = '';
197         if($to ne ''){
198                 $source2 = $wiki->get_backup($pagename, $to);
199         } else {
200                 $source2 = $wiki->get_page($pagename);
201         }
202         my $format  = $wiki->get_edit_format();
203         
204         $source1 = $wiki->convert_from_fswiki($source1, $format);
205         $source2 = $wiki->convert_from_fswiki($source2, $format);
206         
207         my $diff_text = "";
208 =pod
209         my @msg1 = split(/\n/,$source1);
210         return "¥Ú¡¼¥¸¤¬Â礭¤¹¤®¤ë¤¿¤áº¹Ê¬¤òɽ¼¨¤Ç¤­¤Þ¤»¤ó¡£" if($#msg1 >= 999);
211         my @msg2 = split(/\n/,$source2);
212         return "¥Ú¡¼¥¸¤¬Â礭¤¹¤®¤ë¤¿¤áº¹Ê¬¤òɽ¼¨¤Ç¤­¤Þ¤»¤ó¡£" if($#msg2 >= 999);
213 =cut
214         my @msg1 = _str_jfold($source1, 1);
215         my @msg2 = _str_jfold($source2, 1);
216         
217         my $msgrefA = \@msg2;
218         my $msgrefB = \@msg1;
219         
220         traverse_sequences($msgrefA, $msgrefB,
221                 {
222                         MATCH => sub {
223                                 my ($a, $b) = @_;
224                                 $diff_text .= Util::escapeHTML($msgrefA->[$a]);
225                         },
226                         DISCARD_A => sub {
227                                 my ($a, $b) = @_;
228                                 $diff_text .= "<del class=\"diff\">".Util::escapeHTML($msgrefA->[$a])."</del><wbr>";
229                         },
230                         DISCARD_B => sub {
231                                 my ($a, $b) = @_;
232                                 $diff_text .= "<ins class=\"diff\">".Util::escapeHTML($msgrefB->[$b])."</ins><wbr>";
233                         }
234                 });
235         
236         return ($diff_text, $source2 ne "");
237 }
238
239 #==============================================================================
240 # Ê¸»úÎó¤ò»ØÄêʸ»ú¿ô¤òʬ³ä
241 #==============================================================================
242 sub _str_jfold {\r
243   my $str    = shift;       #»ØÄêʸ»úÎó\r
244   my $byte   = shift;       #»ØÄê¥Ð¥¤¥È\r
245   my $j      = new Jcode($str);\r
246   my @result = ();\r
247 \r
248   foreach my $buff ( $j->jfold($byte) ){\r
249     push(@result, $buff);\r
250   }\r
251 \r
252   return(@result);\r
253 }
254
255 #==============================================================================
256 # ¥Ú¡¼¥¸É½¼¨»þ¤Î¥Õ¥Ã¥¯¥á¥½¥Ã¥É
257 # ¡Öº¹Ê¬¡×¥á¥Ë¥å¡¼¤òÍ­¸ú¤Ë¤·¤Þ¤¹
258 #==============================================================================
259 sub hook {
260         my $self = shift;
261         my $wiki = shift;
262         my $cgi  = $wiki->get_CGI;
263         
264         my $pagename = $cgi->param("page");
265         if($wiki->{storage}->backup_type eq 'all'){
266                 $wiki->add_menu("ÍúÎò",$wiki->create_url({ action=>"DIFF",page=>$pagename }));
267         } else {
268                 $wiki->add_menu("º¹Ê¬",$wiki->create_url({ action=>"DIFF",page=>$pagename }));
269         }
270 }
271
272 1;