1
# Plugin for Foswiki - The Free and Open Source Wiki, http://foswiki.org/
3
# Copyright (C) 2004 Crawford Currie
4
# Copyright (C) 2001-2006 Foswiki Contributors.
5
# All Rights Reserved. Foswiki Contributors
6
# are listed in the AUTHORS file in the root of this distribution.
7
# NOTE: Please extend that file, not this notice.
9
# This program is free software; you can redistribute it and/or
10
# modify it under the terms of the GNU General Public License
11
# as published by the Free Software Foundation; either version 2
12
# of the License, or (at your option) any later version. For
13
# more details read LICENSE in the root of this distribution.
15
# This program is distributed in the hope that it will be useful,
16
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
# For licensing info read LICENSE file in the Foswiki root.
21
# Comment Foswiki plugin
22
# Original author David Weller, reimplemented by Peter Masiar
23
# and again by Crawford Currie
25
# This version is specific to Foswiki::Plugins::VERSION > 1.026
35
package Foswiki::Plugins::CommentPlugin::Comment;
37
# PUBLIC save the given comment.
40
#my ( $text, $topic, $web ) = @_;
42
my $wikiName = Foswiki::Func::getWikiName();
44
!Foswiki::Func::checkAccessPermission(
45
'change', $wikiName, '', $_[1], $_[2]
50
# user has no permission to change the topic
51
throw Foswiki::OopsException(
53
def => 'topic_access',
63
# PUBLIC STATIC convert COMMENT statements to form prompts
66
#my ( $previewing, $text, $web, $topic ) = @_;
69
Foswiki::Func::getPreferencesValue('COMMENTPLUGIN_DEFAULT_TYPE')
74
# Is commenting disabled?
78
# We are in Preview mode
79
$message = "(Edit - Preview)";
80
$disable = 'disabled';
85
s/%COMMENT({.*?})?%/_handleInput($1,$_[2],$_[3],\$idx,$message,$disable,$defaultType)/eg;
90
Parses a templatetopic attribute and returns a "Web.Topic" string.
94
sub _getTemplateLocation {
95
my ( $attrtemplatetopic, $web ) = @_;
97
my $templatetopic = '';
98
my $templateweb = $web || '';
99
if ($attrtemplatetopic) {
100
my ( $templocweb, $temploctopic ) =
101
Foswiki::Func::normalizeWebTopicName( $templateweb,
102
$attrtemplatetopic );
103
$templatetopic = "$templocweb.$temploctopic";
105
return $templatetopic;
108
# PRIVATE generate an input form for a %COMMENT tag
110
my ( $attributes, $web, $topic, $pidx, $message, $disable, $defaultType ) =
113
$attributes =~ s/^{(.*)}$/$1/ if ($attributes);
115
my $attrs = new Foswiki::Attrs( $attributes, 1 );
116
my $type = $attrs->remove('type') || $attrs->remove('mode') || $defaultType;
117
my $silent = $attrs->remove('nonotify');
118
my $location = $attrs->remove('location');
119
my $remove = $attrs->remove('remove');
120
my $nopost = $attrs->remove('nopost');
121
my $default = $attrs->remove('default');
122
my $attrtemplatetopic = $attrs->remove('templatetopic') || '';
123
my $templatetopic = _getTemplateLocation( $attrtemplatetopic, $web );
125
$message ||= $default || '';
126
$message ||= $default || '';
129
# clean off whitespace
133
# Expand the template in the context of the web where the comment
134
# box is (not the target of the comment!)
135
my $input = _getTemplate( "PROMPT:$type", $web, $topic, $templatetopic )
137
return $input if $input =~ m/^%RED%/so;
139
# Expand special attributes as required
140
$input =~ s/%([a-z]\w+)\|(.*?)%/_expandPromptParams($1, $2, $attrs)/ieg;
142
# see if this comment is targeted at a different topic, and
143
# change the url if it is.
145
my $target = $attrs->remove('target');
148
# extract web and anchor
149
if ( $target =~ s/^(\w+)\.// ) {
152
if ( $target =~ s/(#\w+)$// ) {
155
if ( $target ne '' ) {
161
if ( $disable eq '' ) {
162
$url = Foswiki::Func::getScriptUrl( $web, $topic, 'save' );
165
my $noform = $attrs->remove('noform') || '';
166
if ( $input !~ m/^%RED%/ ) {
167
$input =~ s/%DISABLED%/$disable/g;
168
$input =~ s/%MESSAGE%/$message/g;
171
if ( $disable eq '' ) {
172
my $hiddenFields = "";
174
"\n" . CGI::hidden( -name => 'comment_action', -value => 'save' );
176
"\n" . CGI::hidden( -name => 'comment_type', -value => $type );
177
if ( defined($silent) ) {
179
"\n" . CGI::hidden( -name => 'comment_nonotify', value => 1 );
181
if ($templatetopic) {
182
$hiddenFields .= "\n"
184
-name => 'comment_templatetopic',
185
-value => $templatetopic
189
$hiddenFields .= "\n"
191
-name => 'comment_location',
196
$hiddenFields .= "\n"
197
. CGI::hidden( -name => 'comment_anchor', -value => $anchor );
200
$hiddenFields .= "\n"
201
. CGI::hidden( -name => 'comment_index', -value => $$pidx );
204
$hiddenFields .= "\n"
205
. CGI::hidden( -name => 'comment_nopost', -value => $nopost );
208
$hiddenFields .= "\n"
209
. CGI::hidden( -name => 'comment_remove', -value => $$pidx );
211
$input .= $hiddenFields;
215
_getTemplate( "FORM:$type", $topic, $web, $templatetopic, 'off' )
218
$form =~ s/%COMMENTPROMPT%/$input/;
222
unless ( $noform eq 'on' ) {
223
$input = CGI::start_form(
237
# PRIVATE get the given template and do standard expansions
239
my ( $name, $topic, $web, $templatetopic, $warn ) = @_;
246
|| Foswiki::Func::getPreferencesValue('COMMENTPLUGIN_TEMPLATES')
249
my $templates = Foswiki::Func::loadTemplate($templateFile);
251
Foswiki::Func::writeWarning(
252
"Could not read template file '$templateFile'");
256
my $t = Foswiki::Func::expandTemplate($name);
257
return "%RED%No such template def TMPL:DEF{$name}%ENDCOLOR%"
258
unless ( defined($t) && $t ne '' ) || $warn eq 'off';
263
# PRIVATE expand special %param|default% parameters in PROMPT template
264
sub _expandPromptParams {
265
my ( $name, $default, $attrs ) = @_;
267
my $val = $attrs->{$name};
268
return $val if defined($val);
272
# PRIVATE STATIC Performs comment insertion in the topic.
275
#my ( $text, $topic, $web ) = @_;
276
my ( $topic, $web ) = ( $_[1], $_[2] );
278
my $query = Foswiki::Func::getCgiQuery();
279
return unless $query;
282
$query->param('comment_type')
283
|| Foswiki::Func::getPreferencesValue('COMMENTPLUGIN_DEFAULT_TYPE')
285
my $index = $query->param('comment_index') || 0;
286
my $anchor = $query->param('comment_anchor');
287
my $location = $query->param('comment_location');
288
my $remove = $query->param('comment_remove');
289
my $nopost = $query->param('comment_nopost');
290
my $templatetopic = $query->param('comment_templatetopic') || '';
292
my $output = _getTemplate( "OUTPUT:$type", $topic, $web, $templatetopic );
293
if ( $output =~ m/^%RED%/ ) {
297
# Expand the template
298
my $position = 'AFTER';
299
if ( $output =~ s/%POS:(.*?)%//g ) {
303
# Expand common variables in the template, but don't expand other
305
$output = Foswiki::Func::expandVariablesOnTopicCreation($output);
307
$output = '' unless defined($output);
309
# SMELL: Reverse the process that inserts meta-data just performed
310
# by the Foswiki core, but this time without the support of the
311
# methods in the core. Fortunately this will work even if there is
312
# no embedded meta-data.
313
# Note: because this is Dakar, and has sensible semantics for handling
314
# the =text= parameter to =save=, there is no longer any need to re-read
315
# the topic. The text is automatically defaulted to the existing topic
316
# text if the =text= parameter isn't specified - which for comments,
322
foreach my $line ( split( /\r?\n/, $_[0] ) ) {
323
if ( $line =~ /^%META:[A-Z]+{[^}]*}%/ ) {
325
$postmeta .= $line . "\n";
328
$premeta .= $line . "\n";
332
$text .= $line . "\n";
337
#make sure the anchor or location exits
338
if ( defined($location) and not( $text =~ /(?<!location\=\")($location)/ ) )
342
if ( defined($anchor) and not( $text =~ /^($anchor\s)/ ) ) {
347
if ( $position eq 'TOP' ) {
348
$text = $output . $text;
350
elsif ( $position eq 'BOTTOM' ) {
352
# Awkward newlines here, to avoid running into meta-data.
353
# This should _not_ be a problem.
354
$text =~ s/[\r\n]+$//;
355
$text .= "\n" unless $output =~ m/^\n/s;
357
$text .= "\n" unless $text =~ m/\n$/s;
361
if ( $position eq 'BEFORE' ) {
364
$text =~ s/(?<!location\=\")($location)/$output$1/m );
369
$text =~ s/(?<!location\=\")($location)/$1$output/m );
372
$text .= "\n" unless $text =~ m/\n$/s;
376
# position relative to anchor
377
if ( $position eq 'BEFORE' ) {
379
unless ( $text =~ s/^($anchor\s)/$output$1/m );
383
unless ( $text =~ s/^($anchor\s)/$1$output/m );
385
$text .= "\n" unless $text =~ m/\n$/s;
389
# Position relative to index'th comment
392
$text =~ s((%COMMENT({.*?})?%.*\n))
393
(&_nth($1,\$idx,$position,$index,$output))eg
397
# If there was a problem adding relative to the comment,
398
# add to the end of the topic
401
$text .= "\n" unless $text =~ m/\n$/s;
406
if ( defined $remove ) {
408
# remove the index'th comment box
410
$text =~ s/(%COMMENT({.*?})?%)/_remove_nth($1,\$idx,$remove)/eg;
413
$_[0] = $premeta . $text . $postmeta;
416
# PRIVATE embed output if this comment is the interesting one
418
my ( $tag, $pidx, $position, $index, $output ) = @_;
420
if ( $$pidx == $index ) {
421
if ( $position eq 'BEFORE' ) {
422
$tag = $output . $tag;
432
# PRIVATE remove the nth comment box
434
my ( $tag, $pidx, $index ) = @_;
435
$tag = '' if ( $$pidx == $index );