/[pub]/suikawiki/script/misc/plugins/view/propedit.wp2
Suika

Contents of /suikawiki/script/misc/plugins/view/propedit.wp2

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations) (download)
Sun Feb 6 12:24:08 2005 UTC (19 years, 8 months ago) by wakaba
Branch: MAIN
CVS Tags: suikawiki3-redirect, HEAD
Branch point for: helowiki-2005, helowiki
Changes since 1.1: +57 -17 lines
Bidirectional linking support added

1 wakaba 1.1 #?SuikaWikiConfig/2.0
2    
3     Plugin:
4     @Name: PropEdit
5     @Description:
6     @@@: WikiPage Property Editor
7     @@lang:en
8     @License: %%Perl%%
9     @Author:
10     @@Name:
11     @@@@: Wakaba
12     @@@lang:ja
13     @@@script:Latn
14     @@Mail[list]: w@suika.fam.cx
15     @Date.RCS:
16 wakaba 1.2 $Date: 2004/07/25 06:54:29 $
17 wakaba 1.1 @RequiredPlugin[list]:
18     WikiEdit
19     WikiFormCore
20     @Namespace:
21     @@media-type:
22     http://suika.fam.cx/~wakaba/-temp/2004/04/24/mt#
23     @@pe:
24     http://suika.fam.cx/~wakaba/archive/2004/7/20/sw-propedit#
25 wakaba 1.2 @@sw:
26     http://suika.fam.cx/~wakaba/archive/2004/7/20/sw#
27 wakaba 1.1
28     PluginConst:
29     @NS_XHTML1:
30     http://www.w3.org/1999/xhtml
31    
32     ViewDefinition:
33     @Mode: pe--propedit
34     @Condition:
35     @@http-method[list]:
36     GET
37     HEAD
38     @Description:
39     @@@: Editing WikiPage Properties
40     @@lang: en
41     @template:
42     @@http-status-code: 200
43     @@media-type: text/html
44     @@use-media-type-charset: 1
45     @@expires: %%edit%%
46     @@body:
47     %html-document (
48     title => {%res(name=>{PropEdit:WebPageTitle});}p,
49     link-meta => {%template (name => links);
50     %html-meta(name => ROBOTS, content => NOINDEX);}p,
51     content => {
52     %template (
53     name => ws--page,
54     -content => {
55     %section (
56     title => {%res (name => {PropEdit:Title});}p, heading,
57     content => {
58     %pe--propedit (template => {
59     %resource-as-plain-text (name => {PropEdit:Template});
60     }p);
61     }p,
62     );
63     },
64     );
65     }p,
66     );
67    
68     ViewDefinition:
69     @Mode: -pe--conflict
70     @Condition:
71     @@http-method[list]:
72     GET
73     @Description:
74     @@@: Editing WikiPage Properties -- Report Confliction
75     @@lang: en
76     @template:
77     @@http-status-code: 409
78     @@media-type: text/html
79     @@use-media-type-charset: 1
80     @@expires: %%error%%
81     @@body:
82     %html-document (
83     title => {%res(name=>{PropEdit:Conflict:WebPageTitle});}p,
84     link-meta => {%template (name => links);
85     %html-meta(name => ROBOTS, content => NOINDEX);}p,
86     content => {
87     %template (
88     name => ws--page,
89     -content => {
90     %section (
91     title => {%res (name => {PropEdit:Conflict:Title});}p, heading,
92     content => {
93     %paragraph (content => {
94     %res (name => {PropEdit:Conflict:Description});
95     }p);
96     %pe--propedit (template => {
97     %resource-as-plain-text (name => {PropEdit:Template});
98     }p,
99     );
100     }p);},
101     );
102     }p,
103     );
104    
105     FormattingRule:
106     @Category[list]: view
107     @Name: pe--propedit
108     @Description:
109     @@@: A property editor form
110     @@lang: en
111     @Parameter:
112     @@Name: page
113     @@Type: WikiName
114     @@Default: (auto)
115     @@Description:
116     @@@@: WikiPage to be edited
117     @@@lang:en
118     @Parameter:
119     @@Name: template
120     @@Type: template
121     @@Default: (required)
122     @@Description:
123     @@@@: Template of the content
124     @@@lang: en
125     @Formatting:
126     __ATTRTEXT:%page__;__ATTRTEXT:%template__;
127     my $page = $o->{wiki}->name ($p->{page} || $o->{wiki}->{var}->{page});
128     my $template = $p->{template};
129     my $content = __FUNCPACK{WikiEdit}__->get_content ($o, $page);
130     local $o->{var}->{content} = $content->{content};
131     local $o->{var}->{content_prop} = $content->{content_prop};
132     local $o->{var}->{source}->{prop} = sub {
133     my %opt = @_;
134     my $key = $opt{p}->{id};
135     my $uri = $opt{o}->{wiki}->{config}->{<Q:pe:prop>}->{$key}->{uri};
136     my $rv = {};
137     if ($uri) {
138     if (my $nv = $opt{o}->{wiki}->{input}->parameter ('PE--CTRL--'.$key)) {
139     $rv->{value} = $nv;
140     $rv->{class} = [qw/pe--from-parameter/];
141     } else {
142     $rv->{value} = $opt{o}->{var}->{content_prop}
143     ->get_attribute_value ($uri,
144     default => $opt{p}->{default});
145     }
146     } else {
147     $rv->{value} = $opt{p}->{default};
148     }
149     $rv;
150     };
151     __FUNCPACK{WikiFormCore}__->make_form_in_html
152     ($p->{-parent}, $template,
153     wiki => $o->{wiki},
154     o => $o,
155     index => -1,
156     local_id_prefix => 'PE--CTRL--',
157     output => {
158     mode => 'pe--write',
159     page => $page,
160     submit_button => 1,
161     hidden => sub {
162     my ($hidden, $o) = @_;
163     ## Embed hidden sequencial number to detect confliction
164     for ($hidden->append_new_node (type => '#element',
165     namespace_uri => $NS_XHTML1,
166     local_name => 'input')) {
167     $_->set_attribute (type => 'hidden');
168     $_->set_attribute (name => 'pe--seq');
169     $_->set_attribute (value => $o->{var}->{content_prop}
170     ->get_attribute_value (<Q:pe:seq>,
171     default => 0));
172     $_->option (use_EmptyElemTag => 1);
173     }
174     },
175     });
176    
177     ViewFragment:
178     @Name: links
179     @Description:
180     @@@: Link to property edit mode of the WikiPage
181     @@lang:en
182     @Formatting:
183     %link-wiki(mode => pe--propedit, up-to-date,
184     rel => edit, class => wiki-cmd,
185     description => {%res(name=>{PropEdit:Link:Description});}p);
186    
187     ViewDefinition:
188     @Mode: pe--write
189     @Condition:
190     @@http-method[list]:
191     POST
192     @Description:
193     @@@: Saving modified (new) WikiPage properties
194     @@lang: en
195     @Use:
196     use Message::Util::Error;
197     @method:
198     @@Name: main
199     @@@:
200     my $wiki = $self->{view}->{wiki};
201     $wiki->{var}->{db}->{read_only}->{'content'} = 1;
202     $wiki->{var}->{db}->{read_only}->{'content_prop'} = 0;
203     $wiki->{var}->{db}->{read_only}->{'lastmodified'} = 1;
204     $wiki->{var}->{db}->{read_only}->{'referer'} = 0;
205     $wiki->init_db;
206    
207     my $page = $wiki->{var}->{page};
208     my $old_content = $wiki->{db}->get (content => $page);
209     my $prop = $wiki->{db}->get (content_prop => $page);
210    
211     ## Check confliction
212     my $seq = $wiki->{input}->parameter ('pe--seq') || 0;
213     if ($seq != $prop->get_attribute_value (<Q:pe:seq>, default => 0)) {
214     $self->{view}->{wiki}->view_in_mode (mode => '-pe--conflict');
215     throw SuikaWiki::DB::Util::Error -type => 'ERROR_REPORTED';
216     }
217 wakaba 1.2
218     my %pprop;
219     ## NOTE: Uniqueness of stringified WikiName assumed.
220     $pprop{my $page_name = $page->stringify (wiki => $wiki)}
221     = {prop => $prop, page => $page};
222     my $this_page_name = $page_name;
223 wakaba 1.1
224     MODIFICATION: {
225    
226     my $old_mt;
227     my $new_mt;
228     my %depend;
229     KEY: for my $key (grep s/^PE--CTRL--//, $wiki->{input}->parameter_names) {
230     my $propinfo = $wiki->{config}->{<Q:pe:prop>}->{$key};
231     next KEY unless $propinfo->{uri};
232    
233     ## Really modified?
234     my $new_value = [$wiki->{input}->parameter ('PE--CTRL--'.$key)];
235     if (@$new_value == 1) {
236     if ($propinfo->{is_list}) {
237     $new_value = [split /\x0A|\x0D\x0A?/, $new_value->[0]];
238     }
239     if ($propinfo->{type} eq <Q:media-type:media-type>) {
240     next KEY if $new_value->[0] eq '#asis';
241     }
242     }
243    
244     my $old_value = $prop->get_attribute_value ($propinfo->{uri});
245     if (ref $old_value and @$new_value == @$old_value) {
246     CHK: {
247     for my $i (0..$#$new_value) {
248     last CHK if $old_value->[$i] ne $new_value->[$i];
249     }
250     next KEY;
251     }
252     } elsif (not ref $old_value and @$new_value == 1) {
253     next KEY if $old_value eq $new_value->[0];
254     }
255     if ($propinfo->{uri} eq <Q:media-type:media-type>) {
256     $old_mt = $old_value;
257     $new_mt = $new_value->[0];
258     }
259 wakaba 1.2
260     ## Update to new value
261 wakaba 1.1 if (@$new_value) {
262     if ($propinfo->{is_list}) {
263     $prop->set_attribute ($propinfo->{uri} => $new_value);
264     } elsif (length $new_value->[0]) {
265     $prop->set_attribute ($propinfo->{uri} => $new_value->[0]);
266     } else {
267     $prop->remove_attribute ($propinfo->{uri});
268     }
269 wakaba 1.2
270     ## Update other page's properties
271     if ($propinfo->{type} eq <Q:sw:WikiName> and
272     defined $propinfo->{<Q:pe:revWNList>}) {
273     PV: for my $wn (@$new_value) {
274     my $wiki_name = $wiki->name ($wn);
275     unless ($pprop{$wn}->{prop}) {
276     $pprop{$wn}->{prop}
277     = $wiki->{db}->get (content_prop => $wiki_name);
278     $pprop{$wn}->{page} = $wiki_name;
279     }
280     my $pv = $pprop{$wn}->{prop}->get_attribute_value
281     ($propinfo->{<Q:pe:revWNList>},
282     as_array => 1);
283     for (@$pv) {
284     next PV if $_ eq $this_page_name;
285     }
286     push @$pv, $this_page_name;
287     $pprop{$wn}->{prop}->set_attribute
288     ($propinfo->{<Q:pe:revWNList>} => $pv);
289     $pprop{$wn}->{modified} = 1;
290     }
291     }
292 wakaba 1.1 } else {
293     $prop->remove_attribute ($propinfo->{uri});
294     }
295 wakaba 1.2 $pprop{$page_name}->{modified} = 1;
296 wakaba 1.1 $depend{$key} = $propinfo->{depend} if $propinfo->{depend};
297     }
298     DEPEND: for my $sub (keys %depend) {
299     for my $main (@{$depend{$sub}}) {
300     unless ($prop->get_attribute ($wiki->{config}->{<Q:pe:prop>}
301     ->{$main}->{uri})) {
302     $prop->remove_attribute ($wiki->{config}->{<Q:pe:prop>}
303     ->{$sub}->{uri});
304     next DEPEND;
305     }
306     }
307     }
308 wakaba 1.2 last MODIFICATION unless $pprop{$page_name}->{modified};
309 wakaba 1.1
310 wakaba 1.2 ## Update property
311     for my $wn (keys %pprop) {
312     next unless $pprop{$wn}->{modified};
313     my $prop = $pprop{$wn}->{prop};
314    
315     my $seq = $prop->get_attribute_value (<Q:pe:seq>, default => 0);
316     $prop->set_attribute (<Q:pe:seq> => $seq + 1);
317 wakaba 1.1
318 wakaba 1.2 try {
319     $self->{view}->{wiki}->{db}->set
320     (content_prop => $pprop{$wn}->{page} => $prop);
321     } catch SuikaWiki::DB::Util::Error with {
322     my $err = shift;
323     if ($err->{-type} eq 'ERROR_REPORTED') {
324     $err->throw;
325     } else {
326     $self->{view}->{wiki}->view_in_mode (mode => '-wdb--fatal-error');
327     throw SuikaWiki::DB::Util::Error -type => 'ERROR_REPORTED';
328     }
329     };
330     }
331 wakaba 1.1
332     ## Post-write events
333     if ($new_mt) {
334     my $format = __FUNCPACK{WikiFormat}__
335     ->handler (\$old_content,
336     serialized_media_type => $old_mt,
337     content_prop => $prop,
338     wiki => $wiki);
339     $format->content_type_changed_from (wiki => $wiki,
340     page => $page,
341     old_content => \$old_content,
342     new_content => \$old_content,
343     new_serialized_media_type => $new_mt,
344     content_prop => $prop);
345     }
346     my $format = __FUNCPACK{WikiFormat}__
347     ->handler (\$old_content,
348     serialized_media_type => $new_mt,
349     content_prop => $prop,
350     wiki => $wiki);
351     $format->content_prop_modified (wiki => $wiki,
352     page => $page,
353     content_prop => $prop);
354 wakaba 1.2 ## ISSUE: Should for other modified WikiPages also fired?
355 wakaba 1.1
356     } # MODIFICATION
357    
358     ## Redirect appropriate mode
359     my $new_mode = $self->{view}->{wiki}->{input}->parameter
360     ('we--mode-modified');
361     $new_mode =~ s/[^0-9A-Za-z._-]+//g;
362     my $uri = $self->{view}->{wiki}->uri_reference
363     (page => $page,
364     mode => $new_mode,
365     up_to_date => 1,
366     param => {we__mode_modified => $new_mode});
367    
368     require SuikaWiki::Output::HTTP;
369     my $output = SuikaWiki::Output::HTTP->new
370     (wiki => $self->{view}->{wiki});
371     $output->set_redirect (uri => $uri, status_code => 303);
372     $output->output (output => 'http-cgi');
373    
374     FormattingRule:
375     @Category[list]:
376     form-input
377     @Name: pe--texts
378     @Description:
379     @@@@: Multiple texts input
380     @@@lang:en
381     @Formatting:
382     __ATTRTEXT:%id__;__ATTRNODE:%label__;
383     my $id = __FUNCPACK{WikiFormCore}__
384     ->control_id ($o,
385     local_id => $p->{id},
386     require_local_id => 1);
387     my $has_label = 0;
388     if ($p->{label}->count) {
389     $has_label = 1;
390     for ($p->{-parent}->append_new_node
391     (type => '#element',
392     namespace_uri => $NS_XHTML1,
393     local_name => 'label')) {
394     $_->set_attribute (for => $id->{global_id});
395     $_->append_node ($p->{label});
396     }
397     $p->{-parent}->append_new_node
398     (type => '#element',
399     namespace_uri => $NS_XHTML1,
400     local_name => 'br')
401     ->option (use_EmptyElemTag => 1);
402     }
403    
404     for ($p->{-parent}->append_new_node (type => '#element',
405     namespace_uri => $NS_XHTML1,
406     local_name => 'textarea')) {
407     $_->set_attribute (name => $id->{local_id});
408     $_->set_attribute (id => $id->{global_id}) if $has_label;
409     __ATTRTEXT:%size__;__ATTRTEXT:%lines__;__ATTRTEXT:%description__;
410     $_->set_attribute (cols => ($p->{size}||20)*2); ## Length
411     $_->set_attribute (title => $p->{description}) if $p->{description};
412     $_->set_attribute (disabled => 'disabled') if $o->{form}->{disabled};
413     __ATTRTEXT:%class__;
414     my @class = split /\s+/, $p->{class};
415     push @class, 'require' if $o->{form}->{require}->{id}->{$p->{id}};
416     __ATTRTEXT:%source__;
417     my $items = 5;
418     if ($p->{source}) {
419     if (ref $o->{var}->{source}->{$p->{source}}) {
420     my $d = $o->{var}->{source}->{$p->{source}}
421     ->(p=>$p, o=>$o, type => <Q:pe:texts>);
422     $_->append_text (ref $d->{value} eq 'ARRAY' ?
423     join "\n", @{$d->{value}} : $d->{value});
424     push @class, @{$d->{class}||[]};
425     $items = @{$d->{value}} + 1 if ref $d->{value} eq 'ARRAY';
426     } else {
427     $_->append_text (ref $o->{var}->{$p->{source}} eq 'ARRAY' ?
428     join "\n", @{$o->{var}->{$p->{source}}} :
429     $o->{var}->{$p->{source}});
430     $items = @{$o->{var}->{$p->{source}}} + 1
431     if ref $o->{var}->{$p->{source}} eq 'ARRAY';
432     }
433     } else {
434     __ATTRTEXT:%default__;
435     $_->append_text ($p->{default}); ## Default value
436     }
437     $_->set_attribute (rows => ($p->{lines} || $items)); ## Lines
438     $_->set_attribute (class => join ' ', @class) if @class;
439     }
440    
441     Resource:
442     @Edit:SaveAnd:pe--propedit:Description:
443     @@lang: en
444     @@@:
445     Save modified property values and show this property-editing
446     mode again.
447     @Edit:SaveAnd:pe--propedit:Label:
448     @@lang: en
449     @@@:
450     Editing Properties
451     @PropEdit:Conflict:Description:
452     @@lang: en
453     @@@:
454     Properties for WikiPage %link-to-wikipage (label => {%link-to-it (
455     label => {%page-name;}p);});
456     has been modified during you are editing them.
457     Please ensure that third-party's modification does not
458     affect your submitting changes.
459     @PropEdit:Conflict:Title:
460     @@lang: en
461     @@@:
462     Confliction - Editing Content Properties
463     @PropEdit:Conflict:WebPageTitle:
464     @@lang: en
465     @@@:
466     CONFLICTION - %page-name; (Editing Content Properties)
467     @PropEdit:Link:Description:
468     @@lang: en
469     @@@: Edit properties of this WikiPage
470     @PropEdit:Template:
471    
472     ## Should be defined in resource WikiPage
473     @PropEdit:Title:
474     @@lang: en
475     @@@:
476     Editing Content Properties
477     @PropEdit:WebPageTitle:
478     @@lang: en
479     @@@:
480     %page-name; (Editing Content Properties)
481    
482    
483    

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24