Filename | /var/www/foswiki11/lib/Foswiki/Plugins/CommentPlugin/Comment.pm |
Statements | Executed 15 statements in 2.16ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 18µs | 32µs | BEGIN@5 | Foswiki::Plugins::CommentPlugin::
1 | 1 | 1 | 12µs | 12µs | BEGIN@10.52 | Foswiki::Plugins::CommentPlugin::
1 | 1 | 1 | 11µs | 99µs | BEGIN@12 | Foswiki::Plugins::CommentPlugin::
1 | 1 | 1 | 10µs | 16µs | BEGIN@6 | Foswiki::Plugins::CommentPlugin::
1 | 1 | 1 | 9µs | 9µs | BEGIN@11.53 | Foswiki::Plugins::CommentPlugin::
1 | 1 | 1 | 8µs | 8µs | BEGIN@8.51 | Foswiki::Plugins::CommentPlugin::
1 | 1 | 1 | 7µs | 7µs | BEGIN@9 | Foswiki::Plugins::CommentPlugin::
0 | 0 | 0 | 0s | 0s | _buildNewTopic | Foswiki::Plugins::CommentPlugin::Comment::
0 | 0 | 0 | 0s | 0s | _expandPromptParams | Foswiki::Plugins::CommentPlugin::Comment::
0 | 0 | 0 | 0s | 0s | _getTemplate | Foswiki::Plugins::CommentPlugin::Comment::
0 | 0 | 0 | 0s | 0s | _getTemplateLocation | Foswiki::Plugins::CommentPlugin::Comment::
0 | 0 | 0 | 0s | 0s | _handleInput | Foswiki::Plugins::CommentPlugin::Comment::
0 | 0 | 0 | 0s | 0s | _nth | Foswiki::Plugins::CommentPlugin::Comment::
0 | 0 | 0 | 0s | 0s | _remove_nth | Foswiki::Plugins::CommentPlugin::Comment::
0 | 0 | 0 | 0s | 0s | prompt | Foswiki::Plugins::CommentPlugin::Comment::
0 | 0 | 0 | 0s | 0s | save | Foswiki::Plugins::CommentPlugin::Comment::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # See bottom of file for license and copyright information | ||||
2 | # | ||||
3 | # This version is specific to Foswiki::Plugins::VERSION > 1.026 | ||||
4 | |||||
5 | 2 | 33µs | 2 | 46µs | # spent 32µs (18+14) within Foswiki::Plugins::CommentPlugin::BEGIN@5 which was called:
# once (18µs+14µs) by Foswiki::Plugins::CommentPlugin::commonTagsHandler at line 5 # spent 32µs making 1 call to Foswiki::Plugins::CommentPlugin::BEGIN@5
# spent 14µs making 1 call to strict::import |
6 | 2 | 31µs | 2 | 22µs | # spent 16µs (10+6) within Foswiki::Plugins::CommentPlugin::BEGIN@6 which was called:
# once (10µs+6µs) by Foswiki::Plugins::CommentPlugin::commonTagsHandler at line 6 # spent 16µs making 1 call to Foswiki::Plugins::CommentPlugin::BEGIN@6
# spent 6µs making 1 call to warnings::import |
7 | |||||
8 | 2 | 26µs | 1 | 8µs | # spent 8µs within Foswiki::Plugins::CommentPlugin::BEGIN@8.51 which was called:
# once (8µs+0s) by Foswiki::Plugins::CommentPlugin::commonTagsHandler at line 8 # spent 8µs making 1 call to Foswiki::Plugins::CommentPlugin::BEGIN@8.51 |
9 | 2 | 28µs | 1 | 7µs | # spent 7µs within Foswiki::Plugins::CommentPlugin::BEGIN@9 which was called:
# once (7µs+0s) by Foswiki::Plugins::CommentPlugin::commonTagsHandler at line 9 # spent 7µs making 1 call to Foswiki::Plugins::CommentPlugin::BEGIN@9 |
10 | 2 | 31µs | 1 | 12µs | # spent 12µs within Foswiki::Plugins::CommentPlugin::BEGIN@10.52 which was called:
# once (12µs+0s) by Foswiki::Plugins::CommentPlugin::commonTagsHandler at line 10 # spent 12µs making 1 call to Foswiki::Plugins::CommentPlugin::BEGIN@10.52 |
11 | 2 | 31µs | 1 | 9µs | # spent 9µs within Foswiki::Plugins::CommentPlugin::BEGIN@11.53 which was called:
# once (9µs+0s) by Foswiki::Plugins::CommentPlugin::commonTagsHandler at line 11 # spent 9µs making 1 call to Foswiki::Plugins::CommentPlugin::BEGIN@11.53 |
12 | 2 | 1.98ms | 2 | 186µs | # spent 99µs (11+87) within Foswiki::Plugins::CommentPlugin::BEGIN@12 which was called:
# once (11µs+87µs) by Foswiki::Plugins::CommentPlugin::commonTagsHandler at line 12 # spent 99µs making 1 call to Foswiki::Plugins::CommentPlugin::BEGIN@12
# spent 87µs making 1 call to CGI::import |
13 | |||||
14 | package Foswiki::Plugins::CommentPlugin::Comment; | ||||
15 | |||||
16 | # PUBLIC save the given comment. | ||||
17 | sub save { | ||||
18 | |||||
19 | #my ( $text, $topic, $web ) = @_; | ||||
20 | |||||
21 | my $wikiName = Foswiki::Func::getWikiName(); | ||||
22 | if ( | ||||
23 | !Foswiki::Func::checkAccessPermission( | ||||
24 | 'change', $wikiName, '', $_[1], $_[2] | ||||
25 | ) | ||||
26 | ) | ||||
27 | { | ||||
28 | |||||
29 | # user has no permission to change the topic | ||||
30 | throw Foswiki::OopsException( | ||||
31 | 'accessdenied', | ||||
32 | def => 'topic_access', | ||||
33 | web => $_[2], | ||||
34 | topic => $_[1] | ||||
35 | ); | ||||
36 | } | ||||
37 | else { | ||||
38 | _buildNewTopic(@_); | ||||
39 | } | ||||
40 | } | ||||
41 | |||||
42 | # PUBLIC STATIC convert COMMENT statements to form prompts | ||||
43 | sub prompt { | ||||
44 | |||||
45 | #my ( $previewing, $text, $web, $topic ) = @_; | ||||
46 | |||||
47 | my $defaultType = | ||||
48 | Foswiki::Func::getPreferencesValue('COMMENTPLUGIN_DEFAULT_TYPE') | ||||
49 | || 'above'; | ||||
50 | |||||
51 | my $message = ''; | ||||
52 | |||||
53 | # Is commenting disabled? | ||||
54 | my $disable = ''; | ||||
55 | if ( $_[0] ) { | ||||
56 | |||||
57 | # We are in Preview mode | ||||
58 | $message = "(Edit - Preview)"; | ||||
59 | $disable = 'disabled'; | ||||
60 | } | ||||
61 | elsif ( Foswiki::Func::getContext->{static} ) { | ||||
62 | $message = "(Static view)"; | ||||
63 | $disable = 'disabled'; | ||||
64 | } | ||||
65 | |||||
66 | my $idx = 0; | ||||
67 | $_[1] =~ | ||||
68 | s/%COMMENT({.*?})?%/_handleInput($1,$_[2],$_[3],\$idx,$message,$disable,$defaultType)/eg; | ||||
69 | } | ||||
70 | |||||
71 | =pod | ||||
72 | |||||
73 | Parses a templatetopic attribute and returns a "Web.Topic" string. | ||||
74 | |||||
75 | =cut | ||||
76 | |||||
77 | sub _getTemplateLocation { | ||||
78 | my ( $attrtemplatetopic, $web ) = @_; | ||||
79 | |||||
80 | my $templatetopic = ''; | ||||
81 | my $templateweb = $web || ''; | ||||
82 | if ($attrtemplatetopic) { | ||||
83 | my ( $templocweb, $temploctopic ) = | ||||
84 | Foswiki::Func::normalizeWebTopicName( $templateweb, | ||||
85 | $attrtemplatetopic ); | ||||
86 | $templatetopic = "$templocweb.$temploctopic"; | ||||
87 | } | ||||
88 | return $templatetopic; | ||||
89 | } | ||||
90 | |||||
91 | # PRIVATE generate an input form for a %COMMENT tag | ||||
92 | sub _handleInput { | ||||
93 | my ( $attributes, $web, $topic, $pidx, $message, $disable, $defaultType ) = | ||||
94 | @_; | ||||
95 | |||||
96 | $attributes =~ s/^{(.*)}$/$1/ if ($attributes); | ||||
97 | |||||
98 | my $attrs = new Foswiki::Attrs( $attributes, 1 ); | ||||
99 | my $type = $attrs->remove('type') || $attrs->remove('mode') || $defaultType; | ||||
100 | my $silent = $attrs->remove('nonotify'); | ||||
101 | my $location = $attrs->remove('location'); | ||||
102 | my $remove = $attrs->remove('remove'); | ||||
103 | my $nopost = $attrs->remove('nopost'); | ||||
104 | my $default = $attrs->remove('default'); | ||||
105 | my $attrtemplatetopic = $attrs->remove('templatetopic') || ''; | ||||
106 | my $templatetopic = _getTemplateLocation( $attrtemplatetopic, $web ); | ||||
107 | |||||
108 | $message ||= $default || ''; | ||||
109 | $message ||= $default || ''; | ||||
110 | $disable ||= ''; | ||||
111 | |||||
112 | # clean off whitespace | ||||
113 | $type =~ m/(\S*)/; | ||||
114 | $type = $1; | ||||
115 | |||||
116 | # Expand the template in the context of the web where the comment | ||||
117 | # box is (not the target of the comment!) | ||||
118 | my $input = _getTemplate( "PROMPT:$type", $web, $topic, $templatetopic ) | ||||
119 | || ''; | ||||
120 | return $input if $input =~ m/^%RED%/so; | ||||
121 | |||||
122 | # Expand special attributes as required | ||||
123 | $input =~ s/%([a-z]\w+)\|(.*?)%/_expandPromptParams($1, $2, $attrs)/ieg; | ||||
124 | |||||
125 | # see if this comment is targeted at a different topic, and | ||||
126 | # change the url if it is. | ||||
127 | my $anchor = undef; | ||||
128 | my $target = $attrs->remove('target'); | ||||
129 | if ($target) { | ||||
130 | |||||
131 | # extract web and anchor | ||||
132 | if ( $target =~ s/^(\w+)\.// ) { | ||||
133 | $web = $1; | ||||
134 | } | ||||
135 | if ( $target =~ s/(#\w+)$// ) { | ||||
136 | $anchor = $1; | ||||
137 | } | ||||
138 | if ( $target ne '' ) { | ||||
139 | $topic = $target; | ||||
140 | } | ||||
141 | } | ||||
142 | |||||
143 | my $url = ''; | ||||
144 | if ( $disable eq '' ) { | ||||
145 | $url = Foswiki::Func::getScriptUrl( $web, $topic, 'save' ); | ||||
146 | } | ||||
147 | |||||
148 | # Note: Item10050: If CommentPlugin prompt adds newlines then it prevents | ||||
149 | # COMMENT inside TML tables so avoid cosmetic \n | ||||
150 | my $noform = $attrs->remove('noform') || ''; | ||||
151 | if ( $input !~ m/^%RED%/ ) { | ||||
152 | $input =~ s/%DISABLED%/$disable/g; | ||||
153 | $input =~ s/%MESSAGE%/$message/g; | ||||
154 | my $n = $$pidx + 0; | ||||
155 | |||||
156 | if ( $disable eq '' ) { | ||||
157 | my $hiddenFields = ""; | ||||
158 | $hiddenFields .= | ||||
159 | CGI::hidden( -name => 'comment_action', -value => 'save' ); | ||||
160 | $hiddenFields .= | ||||
161 | CGI::hidden( -name => 'comment_type', -value => $type ); | ||||
162 | if ( defined($silent) ) { | ||||
163 | $hiddenFields .= | ||||
164 | CGI::hidden( -name => 'comment_nonotify', value => 1 ); | ||||
165 | } | ||||
166 | if ($templatetopic) { | ||||
167 | $hiddenFields .= CGI::hidden( | ||||
168 | -name => 'comment_templatetopic', | ||||
169 | -value => $templatetopic | ||||
170 | ); | ||||
171 | } | ||||
172 | if ($location) { | ||||
173 | $hiddenFields .= CGI::hidden( | ||||
174 | -name => 'comment_location', | ||||
175 | -value => $location | ||||
176 | ); | ||||
177 | } | ||||
178 | elsif ($anchor) { | ||||
179 | $hiddenFields .= | ||||
180 | CGI::hidden( -name => 'comment_anchor', -value => $anchor ); | ||||
181 | } | ||||
182 | else { | ||||
183 | $hiddenFields .= | ||||
184 | CGI::hidden( -name => 'comment_index', -value => $$pidx ); | ||||
185 | } | ||||
186 | if ($nopost) { | ||||
187 | $hiddenFields .= | ||||
188 | CGI::hidden( -name => 'comment_nopost', -value => $nopost ); | ||||
189 | } | ||||
190 | if ($remove) { | ||||
191 | $hiddenFields .= | ||||
192 | CGI::hidden( -name => 'comment_remove', -value => $$pidx ); | ||||
193 | } | ||||
194 | $input .= $hiddenFields; | ||||
195 | } | ||||
196 | if ($noform) { | ||||
197 | my $form = | ||||
198 | _getTemplate( "FORM:$type", $topic, $web, $templatetopic, 'off' ) | ||||
199 | || ''; | ||||
200 | if ($form) { | ||||
201 | $form =~ s/%COMMENTPROMPT%/$input/; | ||||
202 | $input = $form; | ||||
203 | } | ||||
204 | } | ||||
205 | unless ( $noform eq 'on' ) { | ||||
206 | my $startform = CGI::start_form( | ||||
207 | -name => $type . $n, | ||||
208 | -id => $type . $n, | ||||
209 | -action => $url, | ||||
210 | -method => 'post' | ||||
211 | ); | ||||
212 | |||||
213 | # Item10050: CGI may add a trailing new line. | ||||
214 | # This prevents using COMMENT inside TML tables | ||||
215 | $startform =~ s/\n$//; | ||||
216 | |||||
217 | $input = $startform . $input . CGI::end_form(); | ||||
218 | } | ||||
219 | } | ||||
220 | $$pidx++; | ||||
221 | return $input; | ||||
222 | } | ||||
223 | |||||
224 | # PRIVATE get the given template and do standard expansions | ||||
225 | sub _getTemplate { | ||||
226 | my ( $name, $topic, $web, $templatetopic, $warn ) = @_; | ||||
227 | |||||
228 | $warn ||= ''; | ||||
229 | |||||
230 | # Get the templates. | ||||
231 | my $templateFile = | ||||
232 | $templatetopic | ||||
233 | || Foswiki::Func::getPreferencesValue('COMMENTPLUGIN_TEMPLATES') | ||||
234 | || 'comments'; | ||||
235 | |||||
236 | my $templates = Foswiki::Func::loadTemplate($templateFile); | ||||
237 | if ( !$templates ) { | ||||
238 | Foswiki::Func::writeWarning( | ||||
239 | "Could not read template file '$templateFile'"); | ||||
240 | return; | ||||
241 | } | ||||
242 | |||||
243 | my $t = Foswiki::Func::expandTemplate($name); | ||||
244 | return "%RED%No such template def TMPL:DEF{$name}%ENDCOLOR%" | ||||
245 | unless ( defined($t) && $t ne '' ) || $warn eq 'off'; | ||||
246 | |||||
247 | return $t; | ||||
248 | } | ||||
249 | |||||
250 | # PRIVATE expand special %param|default% parameters in PROMPT template | ||||
251 | sub _expandPromptParams { | ||||
252 | my ( $name, $default, $attrs ) = @_; | ||||
253 | |||||
254 | my $val = $attrs->{$name}; | ||||
255 | return $val if defined($val); | ||||
256 | return $default; | ||||
257 | } | ||||
258 | |||||
259 | # PRIVATE STATIC Performs comment insertion in the topic. | ||||
260 | sub _buildNewTopic { | ||||
261 | |||||
262 | #my ( $text, $topic, $web ) = @_; | ||||
263 | my ( $topic, $web ) = ( $_[1], $_[2] ); | ||||
264 | |||||
265 | my $query = Foswiki::Func::getCgiQuery(); | ||||
266 | return unless $query; | ||||
267 | |||||
268 | my $type = | ||||
269 | $query->param('comment_type') | ||||
270 | || Foswiki::Func::getPreferencesValue('COMMENTPLUGIN_DEFAULT_TYPE') | ||||
271 | || 'above'; | ||||
272 | my $index = $query->param('comment_index') || 0; | ||||
273 | my $anchor = $query->param('comment_anchor'); | ||||
274 | my $location = $query->param('comment_location'); | ||||
275 | my $remove = $query->param('comment_remove'); | ||||
276 | my $nopost = $query->param('comment_nopost'); | ||||
277 | my $templatetopic = $query->param('comment_templatetopic') || ''; | ||||
278 | |||||
279 | my $output = _getTemplate( "OUTPUT:$type", $topic, $web, $templatetopic ); | ||||
280 | if ( $output =~ m/^%RED%/ ) { | ||||
281 | die $output; | ||||
282 | } | ||||
283 | |||||
284 | # Expand the template | ||||
285 | my $position = 'AFTER'; | ||||
286 | if ( $output =~ s/%POS:(.*?)%//g ) { | ||||
287 | $position = $1; | ||||
288 | } | ||||
289 | |||||
290 | # Expand common variables in the template, but don't expand other | ||||
291 | # tags. | ||||
292 | $output = Foswiki::Func::expandVariablesOnTopicCreation($output); | ||||
293 | |||||
294 | $output = '' unless defined($output); | ||||
295 | |||||
296 | # SMELL: Reverse the process that inserts meta-data just performed | ||||
297 | # by the Foswiki core, but this time without the support of the | ||||
298 | # methods in the core. Fortunately this will work even if there is | ||||
299 | # no embedded meta-data. | ||||
300 | # Note: because this is Dakar, and has sensible semantics for handling | ||||
301 | # the =text= parameter to =save=, there is no longer any need to re-read | ||||
302 | # the topic. The text is automatically defaulted to the existing topic | ||||
303 | # text if the =text= parameter isn't specified - which for comments, | ||||
304 | # it isn't. | ||||
305 | my $premeta = ''; | ||||
306 | my $postmeta = ''; | ||||
307 | my $inpost = 0; | ||||
308 | my $text = ''; | ||||
309 | foreach my $line ( split( /\r?\n/, $_[0] ) ) { | ||||
310 | if ( $line =~ /^%META:[A-Z]+{[^}]*}%/ ) { | ||||
311 | if ($inpost) { | ||||
312 | $postmeta .= $line . "\n"; | ||||
313 | } | ||||
314 | else { | ||||
315 | $premeta .= $line . "\n"; | ||||
316 | } | ||||
317 | } | ||||
318 | else { | ||||
319 | $text .= $line . "\n"; | ||||
320 | $inpost = 1; | ||||
321 | } | ||||
322 | } | ||||
323 | |||||
324 | #make sure the anchor or location exits | ||||
325 | if ( defined($location) and not( $text =~ /(?<!location\=\")($location)/ ) ) | ||||
326 | { | ||||
327 | undef $location; | ||||
328 | } | ||||
329 | if ( defined($anchor) and $text !~ /^$anchor\s*$/m ) { | ||||
330 | undef $anchor; | ||||
331 | } | ||||
332 | |||||
333 | unless ($nopost) { | ||||
334 | if ( $position eq 'TOP' ) { | ||||
335 | $text = $output . $text; | ||||
336 | } | ||||
337 | elsif ( $position eq 'BOTTOM' ) { | ||||
338 | |||||
339 | # Awkward newlines here, to avoid running into meta-data. | ||||
340 | # This should _not_ be a problem. | ||||
341 | $text =~ s/[\r\n]+$//; | ||||
342 | $text .= "\n" unless $output =~ m/^\n/s; | ||||
343 | $text .= $output; | ||||
344 | $text .= "\n" unless $text =~ m/\n$/s; | ||||
345 | } | ||||
346 | else { | ||||
347 | if ($location) { | ||||
348 | if ( $position eq 'BEFORE' ) { | ||||
349 | $text .= $output | ||||
350 | unless ( | ||||
351 | $text =~ s/(?<!location\=\")($location)/$output$1/m ); | ||||
352 | } | ||||
353 | else { # AFTER | ||||
354 | $text .= $output | ||||
355 | unless ( | ||||
356 | $text =~ s/(?<!location\=\")($location)/$1$output/m ); | ||||
357 | |||||
358 | } | ||||
359 | $text .= "\n" unless $text =~ m/\n$/s; | ||||
360 | } | ||||
361 | elsif ($anchor) { | ||||
362 | |||||
363 | # position relative to anchor | ||||
364 | if ( $position eq 'BEFORE' ) { | ||||
365 | $text .= $output | ||||
366 | unless ( $text =~ s/^($anchor\s)/$output$1/m ); | ||||
367 | } | ||||
368 | else { # AFTER | ||||
369 | $text .= $output | ||||
370 | unless ( $text =~ s/^($anchor\s)/$1$output/m ); | ||||
371 | } | ||||
372 | $text .= "\n" unless $text =~ m/\n$/s; | ||||
373 | } | ||||
374 | else { | ||||
375 | |||||
376 | # Position relative to index'th comment | ||||
377 | my $idx = 0; | ||||
378 | unless ( | ||||
379 | $text =~ s((%COMMENT({.*?})?%.*\n)) | ||||
380 | (&_nth($1,\$idx,$position,$index,$output))eg | ||||
381 | ) | ||||
382 | { | ||||
383 | |||||
384 | # If there was a problem adding relative to the comment, | ||||
385 | # add to the end of the topic | ||||
386 | $text .= $output; | ||||
387 | } | ||||
388 | $text .= "\n" unless $text =~ m/\n$/s; | ||||
389 | } | ||||
390 | } | ||||
391 | } | ||||
392 | |||||
393 | if ( defined $remove ) { | ||||
394 | |||||
395 | # remove the index'th comment box | ||||
396 | my $idx = 0; | ||||
397 | $text =~ s/(%COMMENT({.*?})?%)/_remove_nth($1,\$idx,$remove)/eg; | ||||
398 | } | ||||
399 | |||||
400 | $_[0] = $premeta . $text . $postmeta; | ||||
401 | } | ||||
402 | |||||
403 | # PRIVATE embed output if this comment is the interesting one | ||||
404 | sub _nth { | ||||
405 | my ( $tag, $pidx, $position, $index, $output ) = @_; | ||||
406 | |||||
407 | if ( $$pidx == $index ) { | ||||
408 | if ( $position eq 'BEFORE' ) { | ||||
409 | $tag = $output . $tag; | ||||
410 | } | ||||
411 | else { # AFTER | ||||
412 | $tag .= $output; | ||||
413 | } | ||||
414 | } | ||||
415 | $$pidx++; | ||||
416 | return $tag; | ||||
417 | } | ||||
418 | |||||
419 | # PRIVATE remove the nth comment box | ||||
420 | sub _remove_nth { | ||||
421 | my ( $tag, $pidx, $index ) = @_; | ||||
422 | $tag = '' if ( $$pidx == $index ); | ||||
423 | $$pidx++; | ||||
424 | return $tag; | ||||
425 | } | ||||
426 | |||||
427 | 1 | 3µs | 1; | ||
428 | __END__ |