/[pub]/suikawiki/script/lib/SuikaWiki/Plugin/WikiEdit.wp2
Suika

Contents of /suikawiki/script/lib/SuikaWiki/Plugin/WikiEdit.wp2

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (show annotations) (download)
Thu Oct 30 07:45:10 2003 UTC (22 years, 8 months ago) by wakaba
Branch: MAIN
Changes since 1.1: +255 -166 lines
Remove some obsolete rules

1 #?SuikaWikiConfig/2.0
2
3 Plugin:
4 @Name: WikiEdit
5 @Description:
6 @@@: WikiPage editing components
7 @@lang:en
8 @License: %%GPL%%
9 @Author:
10 @@Name:
11 @@@@: Wakaba
12 @@@lang:ja
13 @@@script:Latn
14 @@Mail[list]: w@suika.fam.cx
15 @Date.RCS: $Date: 2003/10/25 06:37:31 $
16 @RequiredModule[list]:
17 SuikaWiki::Name::Space
18 Digest::SHA1
19 @RequiredPlugin[list]:
20 WikiView
21 WikiStruct
22 WikiLinking
23 WikiFormCore
24 HTML
25
26 PluginConst:
27 @NS_XHTML1:
28 http://www.w3.org/1999/xhtml
29
30 ViewDefinition:
31 @Mode: edit
32 @Condition:
33 @@http-method[list]:
34 GET
35 HEAD
36 @Description:
37 @@@: Edit WikiPage content as whole, as a plaintext
38 @@lang: en
39 @template:
40 @@http-status-code: 200
41 @@media-type: text/html
42 @@use-media-type-charset: 1
43 @@expires: %%edit%%
44 @@body:
45 %html-document (
46 title => {%res(name=>{Edit:WebPageTitle});}p,
47 link-meta => {%template (name => links);
48 %html-meta(name => ROBOTS, content => NOINDEX);}p,
49 content => {
50 %template (
51 name => ws--page,
52 -content => {%template (name => we--edit-body);},
53 );
54 }p,
55 );
56
57 ViewDefinition:
58 @Mode: write
59 @Condition:
60 @@http-method[list]:
61 POST
62 @Description:
63 @@@: Saving modified (new) WikiPage content
64 @@lang: en
65 @method:
66 @@@:
67 my $touch = $self->{view}->{wiki}->{input}->parameter ('we--touch');
68
69 $self->{view}->{wiki}->{var}->{db}->{read_only}->{'content'} = 0;
70 $self->{view}->{wiki}->{var}->{db}->{read_only}->{'lastmodified'} = 0
71 if $touch;
72 $self->{view}->init_db;
73
74 my $page = $self->{view}->{wiki}->{var}->{page};
75
76 ## TODO: Implements access control
77 #if (&frozen_reject()) {
78 #}
79
80 if (not __FUNCPACK__::page_is_editable ($page)) {
81 ## TODO: Implements this
82 # &_do_view_msg (-view => '-error', -page => $main::form{mypage},
83 # error_message => &Resource ('Error:ThisPageIsUneditable'));
84 # return;
85 die "Uneditable!";
86 }
87
88 ## Check confliction
89 my $current_content = $self->{view}->{wiki}->{db}->get (content => $page);
90 if (length $current_content) {
91 my $current_digest = __FUNCPACK__::digest ($current_content,
92 normalize => 1);
93 my $prev_digest
94 = $self->{view}->{wiki}->{input}->parameter ('we--digest');
95 if ($current_digest ne $prev_digest) {
96 ## TODO: Implements this
97 # _do_view_msg (-view => '-conflict', -page => $page_name);
98 # die "@{[join '//', @$page]}: Conflict : (current) $current_digest [$current_content] vs (prev) $prev_digest";
99 return $self->{view}->{wiki}->view_in_mode
100 (mode => '-conflict');
101 }
102 }
103
104 my $new_content
105 = $self->{view}->{wiki}->{input}->parameter ('we--content');
106 if (length $new_content) {
107 $self->{view}->{wiki}->{db}->set (content => $page => $new_content);
108 if ($touch) {
109 $self->{view}->{wiki}->{db}->set (lastmodified => $page => time);
110 }
111
112 ## TODO: Use SuikaWiki 3 interface
113 my $new_mode = $self->{view}->{wiki}->{input}->parameter
114 ('we--mode-modified');
115 $new_mode =~ s/[^0-9A-Za-z._-]+//g;
116 my $uri = SuikaWiki::Plugin->_uri_wiki_page (join ('//', @$page),
117 mode => $new_mode,
118 with_lm => 1,
119 absolute => 1);
120 $uri .= qq<;we--mode-modified=$new_mode>;
121
122 require SuikaWiki::Output::HTTP;
123 my $output = SuikaWiki::Output::HTTP->new
124 (wiki => $self->{view}->{wiki});
125 $output->set_redirect (uri => $uri, status_code => 303);
126 $output->output (output => 'http-cgi');
127 } else {
128 for (qw/content lastmodified/) {
129 $self->{view}->{wiki}->{db}->delete (content => $page);
130 }
131 $self->{view}->{wiki}->view_in_mode (mode => '-deleted');
132 }
133 @@Name: main
134
135 ViewDefinition:
136 @Mode: adminedit
137 @Condition:
138 @@http-method[list]:
139 GET
140 HEAD
141 @Description:
142 @@@: Edit WikiPage content as whole, as a plaintext (administrator mode)
143 @@lang: en
144 @template:
145 @@http-status-code: 200
146 @@media-type: application/xhtml+xml
147 @@use-media-type-charset: 1
148 @@expires: %%edit%%
149 @@body:
150 %html-document (
151 title => {%res(name=>{Edit:Admin:WebPageTitle});}p,
152 link-meta => {%predefined-template(name=>links);
153 %html-meta(name=>ROBOTS,content=>NOINDEX);}p,
154 content => {
155 %template (
156 name => ws--page,
157 -content => {%template (name => we--adminedit-body);},
158 );
159 }p,
160 );
161
162 ViewDefinition:
163 @Mode: -conflict
164 @Condition:
165 @@http-method[list]:
166 GET
167 HEAD
168 @Description:
169 @@@: Confliction message
170 @@lang: en
171 @template:
172 @@http-status-code: 409
173 @@media-type: text/html
174 @@use-media-type-charset: 1
175 @@body:
176 %html-document (
177 title => {%res(name=>{Edit:Conflict:WebPageTitle});}p,
178 link-meta => {%template(name=>links);
179 %html-meta(name=>ROBOTS,content=>NOINDEX);}p,
180 content => {
181 %template (
182 name => ws--page,
183 -content => {
184 %section (level=>2,
185 title => {%res(name=>{Edit:Conflict:Title});}p, heading,
186 content => {%template (name => we--conflict-body);}p,
187 );
188 },
189 );
190 }p,
191 );
192
193 ViewDefinition:
194 @Mode: -deleted
195 @Condition:
196 @@http-method[list]:
197 GET
198 HEAD
199 @Expires:%%view%%
200 @Description:
201 @@@: Confliction message
202 @@lang: en
203 @template:
204 @@http-status-code: 200
205 @@media-type: text/html
206 @@use-media-type-charset: 1
207 @@body:
208 %html-document (
209 title => {%res (name => {Edit:Deleted:WebPageTitle});}p,
210 link-meta => {%template (name => links);
211 %html-meta (name => ROBOTS, content => NOINDEX);}p,
212 content => {
213 %template (
214 name => ws--page,
215 -content => {
216 %section (level=>2,
217 title => {%res(name=>{Edit:Deleted:Title});}p, heading,
218 content => {
219 %paragraph (content => {%res
220 (name => {Edit:Deleted:Description});}p);
221 }p,
222 );
223 },
224 );
225 }p,
226 );
227
228 ViewFragment:
229 @Name: links
230 @Description:
231 @@@: Link to edit mode of the WikiPage
232 @@lang:en
233 @Formatting:
234 %link-wiki(mode=>edit,rel=>edit,class=>wiki-cmd,
235 title=>{%res(name=>{Link:Edit:Description});}p,up-to-date);
236 %link-wiki(mode=>adminedit,rel=>edit,class=>wiki-cmd,
237 title=>{%res(name=>{Link:AdminEdit:Description});}p,up-to-date);
238
239 ViewFragment:
240 @Name: navbar
241 @Description:
242 @@@: Link to edit mode of the WikiPage
243 @Order: 10
244 @Formatting:
245 %anchor-wiki (mode=>edit,rel=>edit,class=>wiki-cmd,
246 label=>{%res(name=>EditThisPage);}p,
247 title=>{%res(name=>EditThisPageLong);}p,
248 accesskey=>E,add-param=>{#edit});
249
250 ViewFragment:
251 @Template[list]:
252 we--conflict-body
253 @Order: 30
254 @Description:
255 @@@: Conflict report
256 @@lang:en
257 @Formatting:
258 %paragraph (content=>{%res(name=>{Edit:Conflict:Description});}p);
259 %we--conflict-modified-content;
260 %section (level=>3,
261 id => edit-conflict-diff,
262 title => {%res(name=>{Edit:Conflict:Diff:Title});}p, heading,
263 content => {
264 %paragraph (
265 content => {%res(name=>{Edit:Conflict:Diff:Description});}p);
266 %conflict-diff;
267 }p,
268 );
269
270 ViewFragment:
271 @Template[list]: we--edit-body
272 @Order:80
273 @Description:
274 @@@: Editing WikiPage form section
275 @@lang:en
276 @Formatting:
277 %section (level=>2,
278 id => edit,
279 title => {%res (name => {Edit:Title});}p, heading,
280 content => {%edit-form;}p,
281 );
282
283 ViewFragment:
284 @Template[list]: we--adminedit-body
285 @Order:80
286 @Description:
287 @@@: Editing WikiPage form section (Admin edit mode)
288 @@lang:en
289 @Formatting:
290 %section (level=>2,
291 id => edit,
292 title => {%res(name=>{Edit:Title});}p, heading,
293 content => {%edit-form(admin);}p,
294 );
295
296 ViewFragment:
297 @Template[list]: we--conflict-body
298 @Order: 80
299 @Description:
300 @@@: Editing-WikiPage-form section (conflict mode)
301 @@lang:en
302 @Formatting:
303 %section (level=>2,
304 id => edit,
305 title => {%res(name=>{Edit:Title});}p, heading,
306 content => {
307 %paragraph(name=>{%res(name=>{Edit:Conflict:Edit:Description});}p);
308 %edit-form;
309 }p,
310 );
311
312 ViewFragment:
313 @Name: we--edit
314 @Description:
315 @@@: Edit form --- main textarea
316 @@lang:en
317 @Order: 0
318 @Formatting:
319 %textarea(id=>we--content,size=>{%res(name=>{Edit:Form:Size});}p,
320 lines=>{%res(name=>{Edit:Form:Lines});}p);
321
322 ViewFragment:
323 @Name: we--edit
324 @Description:
325 @@@: Submit button
326 @@lang:en
327 @Order: 200
328 @Formatting:
329 %submit(label=>{%res(name=>{Edit:Save});}p);
330
331 FormattingRule:
332 @Category[list]: view
333 @Name: edit-form
334 @Description:
335 @@@: Provides WikiPage editing form
336 @@lang: en
337 @Parameter:
338 @@Name: admin
339 @@Type: boolean
340 @@Default: {0}
341 @@Description:
342 @@@@: Whether administrator's editing mode or not
343 @@@lang:en
344 @Formatting:
345 if (not __FUNCPACK__::page_is_editable ($o->{wiki}->{var}->{page})) {
346 $r = '<p>'.$o->resource('Error:ThisPageIsUneditable',escape=>1).'</p>';
347 # } elsif (!$p->{admin} && &main::is_frozen ($o->{page})) {
348 # $r = '<p>'.$o->resource('Error:ThisPageIsUneditable',escape=>1).'</p>';
349 } else {
350 #$r = '<p>'.$o->resource('Error:PasswordIsNotSpecified',escape=>1).'</p>' if $p->{admin};
351
352 $r = Message::Markup::XML->new (type => '#element',
353 namespace_uri => $NS_XHTML1,
354 local_name => 'form');
355 $r->set_attribute (method => 'post');
356 ## TODO: Use SuikaWiki 3 interface
357 $r->set_attribute (action => $o->uri ('wiki'));
358 $r->set_attribute ('accept-charset' => 'iso-2022-jp utf-8');
359 for ($r->append_new_node (type => '#element',
360 namespace_uri => $NS_XHTML1,
361 local_name => 'input')) {
362 $_->set_attribute (type => 'hidden');
363 $_->set_attribute (name => 'mypage');
364 ## TODO: Use SuikaWiki 3 interface
365 $_->set_attribute (value => join '//', @{$o->{wiki}->{var}->{page}});
366 $_->option (use_EmptyElemTag => 1);
367 }
368 for ($r->append_new_node (type => '#element',
369 namespace_uri => $NS_XHTML1,
370 local_name => 'input')) {
371 $_->set_attribute (type => 'hidden');
372 $_->set_attribute (name => 'mode');
373 $_->set_attribute (value => 'write');
374 $_->option (use_EmptyElemTag => 1);
375 }
376 ## _charset_ hack
377 for ($r->append_new_node (type => '#element',
378 namespace_uri => $NS_XHTML1,
379 local_name => 'input')) {
380 $_->set_attribute (type => 'hidden');
381 $_->set_attribute (name => '_charset_');
382 $_->option (use_EmptyElemTag => 1);
383 }
384
385 my $ovar_orig = $o->{var};
386 $o->{var} = {
387 #content
388 is_admin_mode => $p->{admin},
389 is_conflict_mode => 0,
390 #is_new_page_template
391 };
392 $o->{var}->{content} = __FUNCPACK__::get_content
393 ($o, $o->{wiki}->{var}->{page});
394 for ($r->append_new_node (type => '#element',
395 namespace_uri => $NS_XHTML1,
396 local_name => 'input')) {
397 $_->set_attribute (type => 'hidden');
398 $_->set_attribute (name => 'we--digest');
399 $_->set_attribute (value => ($o->{var}->{is_new_page_template}?'':
400 __FUNCPACK__::digest ($o->{var}->{content},
401 normalize => 1)));
402 $_->option (use_EmptyElemTag => 1);
403 }
404
405 my $formatter = $o->formatter ('we__edit');
406 $r->append_node ($formatter->replace
407 ($o->{wiki}->{view}->assemble_template
408 ('we__edit'),
409 $o, {formatter => $formatter}),
410 node_or_text => 1);
411 $o->{var} = $ovar_orig;
412 }
413
414 FormattingRule:
415 @Category[list]: view
416 @Name: we--conflict-modified-content
417 @Description:
418 @@@:
419 Modified content that is conflicted with current content
420 @@lang:en
421 @Formatting:
422 $r = Message::Markup::XML->new (type => '#element',
423 namespace_uri => $NS_XHTML1,
424 local_name => 'pre');
425 $r->append_text (scalar $o->{wiki}->{input}->parameter ('we--content'));
426
427 FormattingRule:
428 @Category[list]:view
429 @Name: conflict-diff
430 @Description:
431 @@@:
432 Provides marked diff between latest WikiPage content and
433 submitted one
434 @@lang:en
435 @Formatting:
436 require Algorithm::Diff;
437 $r = Message::Markup::XML->new (type => '#element',
438 namespace_uri => $NS_XHTML1,
439 local_name => 'pre');
440 $r->set_attribute (class => 'diff');
441 for (Algorithm::Diff::diff (
442 [split /\x0D?\x0A/,
443 scalar $o->{wiki}->{input}->parameter ('we--content')],
444 [split /\x0D?\x0A/,
445 $o->{wiki}->{db}->get (content
446 => $o->{wiki}->{var}->{page})]
447 )) {
448 for (@{$_}) {
449 my ($sign, $lineno, $text) = @{$_};
450 my $ename = $sign eq '+' ? 'ins' : $sign eq '-' ? 'del' : 'span';
451 my $line = $r->append_new_node (type => '#element',
452 namespace_uri => $NS_XHTML1,
453 local_name => ({qw/+ ins - del/}->{$sign}||'span'));
454
455 $line->set_attribute (class => 'line');
456 for ($line->append_new_node (type => '#element',
457 namespace_uri => $NS_XHTML1,
458 local_name => 'span')) {
459 $_->set_attribute (class => 'lineno');
460 $_->append_text ($lineno);
461 }
462 $line->append_text (' ');
463 for ($line->append_new_node (type => '#element',
464 namespace_uri => $NS_XHTML1,
465 local_name => 'span')) {
466 $_->set_attribute (class => 'sign');
467 $_->append_text ($sign);
468 }
469 $line->append_text (' ');
470 for ($line->append_new_node (type => '#element',
471 namespace_uri => $NS_XHTML1,
472 local_name => 'span')) {
473 $_->set_attribute (class => 'content');
474 $_->append_text ($text);
475 }
476 $line->append_text ("\n");
477 } # diff lines
478 }
479
480 FormattingRule:
481 @Name:mode-after-edit-selection
482 @Category[list]:we--edit
483 @Parameter:
484 @@Name: name
485 @@Type: html4:name
486 @@Default:"we--mode-modified"
487 @@Description:
488 @@@@:Form control name for the selection
489 @@@lang:en
490 @Formatting:
491 my $magic = '';
492 $magic = $1 if $o->{var}->{content} =~ m/^([^\x0A\x0D]+)/s;
493
494 my $name = $p->{name} || 'we--mode-modified';
495 my $selected_mode = $o->{wiki}->{input}->parameter ($name);
496 unless ($selected_mode) {
497 if ($magic =~ /C(?:on(?:fig|st)|SS)/) {
498 $selected_mode = 'edit';
499 } else {
500 $selected_mode = 'default';
501 }
502 }
503
504 my $SELECT = Message::Markup::XML->new (type => '#element',
505 namespace_uri => $NS_XHTML1,
506 local_name => 'select');
507 $SELECT->set_attribute (name => $name);
508 for (qw/default read edit/) {
509 for my $OPTION ($SELECT->append_new_node (type => '#element',
510 namespace_uri => $NS_XHTML1,
511 local_name => 'option')) {
512 $OPTION->set_attribute (value => $_);
513 my $label = $o->resource ('Edit:SaveAnd:'.$_.':Label');
514 $OPTION->set_attribute (label => $label);
515 $OPTION->append_text ($label);
516 $OPTION->set_attribute
517 (title => $o->resource ('Edit:SaveAnd:'.$_.':Description'));
518 $OPTION->set_attribute (selected => 'selected')
519 if $selected_mode eq $_;
520 }
521 }
522 $SELECT;
523
524 Resource:
525 @Edit:Conflict:Title:
526 @@@:Confliction detected!
527 @@lang:en
528 @Edit:Conflict:WebPageTitle:
529 @@@:%page-name; (Edit : 409 CONFLICTION)
530 @@lang:en
531 @Edit:Deleted:Description:
532 @@@:Content of WikiPage %page-name; has been removed.
533 @@lang:en
534 @Edit:Deleted:Title:
535 @@@:WikiPage Deleted
536 @@lang:en
537 @Edit:Deleted:WebPageTitle:
538 @@@:%page-name; (Deleted)
539 @@lang:en
540 @Edit:Form:Lines:15
541 @Edit:Form:Size:18
542 @Edit:Save:
543 @@@:Save
544 @@lang:en
545 @Edit:SaveAnd:default:Description:
546 @@@: Save modified content and show content with your default view mode
547 @@lang:en
548 @Edit:SaveAnd:default:Label:
549 @@@: Default view
550 @@lang:en
551 @Edit:SaveAnd:edit:Description:
552 @@@: Save modified content and show content in the edit mode again
553 @@lang:en
554 @Edit:SaveAnd:edit:Label:
555 @@@: Edit again
556 @@lang:en
557 @Edit:SaveAnd:read:Description:
558 @@@: Save modified content and show content in the read mode
559 @@lang:en
560 @Edit:SaveAnd:read:Label:
561 @@@: Show content
562 @@lang:en
563 @EditThisPage:
564 @@@: Edit
565 @@lang:en
566 @EditThisPageLong:
567 @@@: Edit this WikiPage
568 @@lang:en
569 @Edit:WebPageTitle:
570 @@@: %page-name; (Modification)
571 @@lang:en
572 @Edit:Title:
573 @@@: Modification of the WikiPage
574 @@lang:en
575 @Link:AdminEdit:Description:
576 @@@: Edit this WikiPage (administrator's mode)
577 @@lang:en
578 @Link:Edit:Description:
579 @@@: Edit this WikiPage
580 @@lang:en
581
582 Function:
583 @Name:digest
584 @Description:
585 @@@: Compute digest of given string
586 @@lang:en
587 @Main:
588 my ($s, %opt) = @_;
589 require Digest::SHA1;
590 if ($opt{normalize}) {
591 $s =~ s/\x0D\x0A/\x0A/g;
592 $s =~ tr/\x0D/\x0A/;
593 }
594 Digest::SHA1::sha1_base64 ($s);
595
596 Function:
597 @Name:get_content
598 @Description:
599 @@@:Get WikiPage content to be modified. For new (currently not exist)
600 WikiPage, new page template content is returned.
601 @@lang:en
602 @Main:
603 my ($o, $page) = @_;
604 my $content;
605 $content = $o->{wiki}->{db}->get (content => $page);
606
607 unless (length $content) {
608 ## TODO: use namespaced template page
609 $content = $o->{wiki}->{db}->get
610 (content => $o->{wiki}->{config}->{page}->{NewPageTemplate});
611 $o->{var}->{is_new_page_template} = 1;
612 }
613 $content;
614
615 Function:
616 @Name:page_is_editable
617 @Description:
618 @@@:
619 Returns whether the WikiPage is editable or not.
620 Note that this function is temporary.
621 @@lang:en
622 @Main:
623 my ($page) = @_;
624 $page = join '//', $page;
625 return 0 unless SuikaWiki::Name::Space::validate_name ($page);
626 return 0 if $page =~ /[\x00-\x20\[\]\x7F]/;
627 1;
628
629 Parameter:
630 @Name: we--content
631 @Type: text
632 @Default: ""
633 @Description:
634 @@@:
635 Content of WikiPage (to be)
636 @@lang:en
637
638 Parameter:
639 @Name: we--digest
640 @Type: "Base64ed SHA1"
641 @Default: {undef}
642 @Description:
643 @@@:
644 SHA1 digest value of the WikiPage content before the modification.
645 This value is used to detect confliction of modifying.
646 Empty value (undef or length-zero-string) means that
647 there were no WikiPage content.
648 @@lang:en
649
650 Parameter:
651 @Name: we--mode-modified
652 @Type: mode-name
653 @Default: "default"
654 @Description:
655 @@@:
656 WikiEngine running mode to be specified after modification is completed
657 @@lang:en
658
659 Parameter:
660 @Name: we--touch
661 @Type: form:checkbox-value
662 @Default: "off"
663 @Description:
664 @@@:
665 Whether last-modified date-time of the WikiPage should be updated or not
666 when the WikiPage is modified.
667 @@lang:en

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24