Changeset 8955
- Timestamp:
- 09/07/10 13:55:28 (21 months ago)
- Location:
- trunk/CommentPlugin
- Files:
-
- 9 edited
-
data/System/CommentPlugin.txt (modified) (10 diffs)
-
data/System/CommentPluginTemplate.txt (modified) (3 diffs)
-
data/System/VarCOMMENT.txt (modified) (1 diff)
-
lib/Foswiki/Plugins/CommentPlugin.pm (modified) (2 diffs)
-
lib/Foswiki/Plugins/CommentPlugin/Comment.pm (modified) (6 diffs)
-
lib/Foswiki/Plugins/CommentPlugin/Config.spec (modified) (1 diff)
-
lib/Foswiki/Plugins/CommentPlugin/MANIFEST (modified) (2 diffs)
-
pub/System/CommentPlugin/comment_src.js (modified) (1 diff)
-
test/unit/CommentPlugin/CommentPluginTests.pm (modified) (22 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/CommentPlugin/data/System/CommentPlugin.txt
r8843 r8955 17 17 * signed or unsigned, dated or undated (as defined by a template), 18 18 * in other topics, or other positions within the current topic. 19 20 Supports the definition of custom templates for prompts and for formatting 21 what is placed into topics. 22 23 Supports custom access controls, allowing you to use it to add content to 24 topics where the commenting user doesn't have CHANGE permissions. 19 25 20 26 ---++ Syntax … … 82 88 * some familiarity with the [[%SYSTEMWEB%.SkinTemplates][Skin Templates]]. 83 89 84 To define a comment type, you have to provide two simple template definitions in the template file; one for the prompt box, and one for the generated output. If we have a template type "mytype", these are named =PROMPT:mytype= and =OUTPUT:mytype= respectively. See =comments.tmpl= in the templates directory for examples.90 To define a comment type, you have to provide at least two simple template definitions in the template file; one for the prompt box, and one for the generated output. If we have a template type "mytype", these are named =PROMPT:mytype= and =OUTPUT:mytype= respectively. See =comments.tmpl= in the templates directory for examples. 85 91 86 92 The plugin picks up these template definitions from a standard template file, =templates/comments.tmpl=. This allows different templates to be defined for different Foswiki skins. … … 130 136 The =PROMPT= template defines the contents of an HTML form that is used to capture the comment. This form invokes the comment generator when submitted. Parameters to the comment generator are defined using standard HTML input fields, such as =input=, =textarea= and =select=. The user enters values for these parameters, and these are then available when the =OUTPUT= template is expanded, in the form of <code>%<nop>URLPARAM%</code>s. 131 137 132 Only the input fields of the form need be defined. The plugin automatically generates the <code><form></code> and <code></form></code> tags, unless you specify =noform="on"=, in which case you have to provide them yourself. *Note* that you must define a "submit" button if you want the form to work! 138 ---+++ The =FORM= template 139 The =FORM= template can optionally be provided if you want to explicitly 140 define the form (the <code><form></code> and <code></form></code> tHTML ags) that wraps around the =PROMPT= template. If you don't define 141 a =FORM=template, one is automatically generated for you (unless the =noform="on"= parameter is given). 133 142 134 143 #MoreAttrs … … 152 161 | =%<nop>DISABLED%= | Set to 'disabled' when you cannot comment (e.g. in preview mode). | 153 162 | =%<nop>MESSAGE%= | The text specified by =default=. This may be overridden by a helpful message when the prompt is DISABLED. | 163 164 Within a =FORM= definition, the body of the prompt is expanded to replace 165 the =%<nop>COMMENTPROMPT%= macro. 154 166 155 167 *EXPERT* Note that when a comment is saved, the =save= script is invoked on the target topic, with a number of parameters provided by the comment form. Normally the CommentPlugin will provide these fields in the form, but experts can also provide the fields themselves in order to get finer control over what is submitted, or you might want to define your own HTML forms that do comment submission. The parameters that the CommentPlugin recognises are as follows: … … 193 205 <verbatim class="tml"> 194 206 %COMMENT{ 195 noform="on"196 207 type="example" 197 208 templatetopic="Sandbox.CommentPluginTemplateExample" … … 215 226 216 227 All the [[TemplateTopics#TemplateTopicsVars][usual macros]] that can be used in a topic template can also be used in an =OUTPUT= template. 228 229 ---+++ Custom access controls 230 Using =configure=, the plugin can be configured to use a different access control domain than the default CHANGE. This allows you to use the plugin to add content to topics where the commenting user does not have CHANGE (or even VIEW) access. 217 231 218 232 ---++ Settings … … 228 242 229 243 #Installation 230 ---++ Plugin Installation Instructions 231 * This plugin is pre-installed in most releases. However if you need to upgrade the plugin for any reason: 232 * Download the archive file from the Extensions web (see below) 233 * Unpack the archive in your Foswiki installation directory. 234 * You may need to correct file permissions 235 * Run ==%TOPIC%_installer== to automatically check and install other modules that this module depends on, and enable the plugin. 236 * Alternatively, 237 * Manually resolve the dependencies listed below. 238 %$DEPENDENCIES% 239 * Use =configure= to enable the plugin 244 ---++ Installation Instructions 245 %$INSTALL_INSTRUCTIONS% 240 246 241 247 Note that if you want to use the =action= template then you must also: … … 243 249 1 Put the !CommentPlugin *before* the !ActionTrackerPlugin in the ={PluginsOrder}= configuration option (in =configure=) 244 250 245 ---++ PluginInfo251 ---++ Info 246 252 247 253 Another great extension from the <a style="text-decoration:none" href="http://wikiring.com"><img src="%ATTACHURLPATH%/wikiringlogo20x20.png" alt="" /> *WikiRing* </a> - working together to improve your wiki experience! … … 253 259 | Version: | %$VERSION% | 254 260 | Change History: | | 261 | 31 Aug 2010 | Foswikitask:Item3499: support COMMENT (and other) ACL preferences. Foswikitask:Item9592: added AJAX example. | 255 262 | 31 Jul 2010 | Foswikitask:Item9415 - Documentation updates | 256 263 | 27 May 2010 | Moved example topic Sandbox.CommentPluginExamples to Sandbox web. | … … 265 272 | Support: | http://foswiki.org/Support/%TOPIC% | 266 273 267 *Related Topics:* %USERSWEB%.SitePreferences, [[%SYSTEMWEB%.Plugins][Plugins]]268 269 274 %META:FILEATTACHMENT{name="wikiringlogo20x20.png" attr="h" comment="" version="1"}% -
trunk/CommentPlugin/data/System/CommentPluginTemplate.txt
r8843 r8955 1 1 %META:TOPICINFO{author="ProjectContributor" date="1166310108" format="1.1" version="$Rev$"}% 2 2 %META:TOPICPARENT{name="CommentPlugin"}% 3 4 <!-- %JQREQUIRE{"chili"}% --> 3 5 4 6 ---+!! Templates for CommentPlugin … … 371 373 </verbatim> 372 374 375 ---++++ ajax 376 Post to the current topic using AJAX. This template is paired with 377 comment_src.js (in the pub area for 378 the plugin). The template is very similar to 'above', except that it uses an 379 asynchronous save and the topic is not refreshed, instead the Javascript 380 inserts a "temporary" comment in the DOM. It is intended as an example 381 which you can copy to create your own wowie-zowie jquery comment box. And 382 contribute it back to the community, of course! 383 384 <verbatim class="tml"> 385 %TMPL:DEF{FORM:ajax}%%TMPL:P{"LIBJS" id="COMMENTPLUGIN_AJAX" id="CommentPlugin/comment"}%<form class="commentPluginForm" action="%SCRIPTURL{rest}%/CommentPlugin/comment"> 386 <input type="hidden" name="topic" value="%WEB%.%TOPIC%"/> 387 <input type="hidden" name="comment_ajax" value="1"/> 388 %COMMENTPROMPT%</form>%TMPL:END% 389 %TMPL:DEF{PROMPT:ajax}% 390 <div class="commentPlugin commentPluginPromptBox"> 391 <table border="0" cellpadding="0" cellspacing="0"> 392 <tr valign="middle"> 393 <td> 394 <textarea %DISABLED% rows="%rows|3%" cols="%cols|70%"\ 395 name="comment" class="commentPluginAjax foswikiInputField"\ 396 wrap="soft" title="%MESSAGE%">%MESSAGE%</textarea> 397 </td> 398 <td> <input %DISABLED% type="button"\ 399 value="%button|Add comment%" class="commentPluginAjax foswikiButton" /> 400 <br/><small class="commentPluginStatusResponse"></small> 401 </td> 402 </tr> 403 </table> 404 </div><!--/commentPlugin-->%TMPL:END% 405 </verbatim> 406 <verbatim class="tml"> 407 %TMPL:DEF{OUTPUT:ajax}%%POS:BEFORE%%TMPL:P{OUTPUT:threadmode}%%TMPL:END% 408 </verbatim> 409 373 410 %ICON{"hand"}% See rendered template [[Sandbox.CommentPluginExamples#return][return]] 374 411 375 412 376 377 378 413 ---++ Include !UserComments 379 414 … … 381 416 382 417 <verbatim class="tml">%TMPL:INCLUDE{"UserComments"}%</verbatim> 383 <!-- %JQREQUIRE{"chili"}% --> 418 -
trunk/CommentPlugin/data/System/VarCOMMENT.txt
r8843 r8955 8 8 | *Name* | *Description* | *Default* | 9 9 | =type= | This is the name of the template to use for this comment. Comment templates are defined in a Foswiki template - see [[CommentPlugin#TemPlates][Customisation]], below. If this attribute is not defined, the type is whatever is defined by COMMENTPLUGIN_DEFAULT_TYPE, either in this topic or in your WebPreferences. | =below= | 10 | =default= | Default text to put into the textarea of theprompt. | |10 | =default= | Default text to put into the prompt. | | 11 11 | =target= | Name of the topic to add the comment to | the current topic | 12 12 | =location= | Regular expression specifying the comment location in the target topic. Read _carefully_ the CommentPlugin documentation! | | 13 13 | =mode= | For compatibility with older versions only, synonymous with =type= | | 14 14 | =nonotify= | Set to "on" to disable change notification for target topics | =off= | 15 | =noform= | Set to "on" to disable the automatic form that encloses your comment block - _remember_ to insert =<form>= tags yourself!See [[Sandbox.CommentPluginExamples#noform][CommentPluginExamples:noform]] for an example. | =off= |15 | =noform= | Set to "on" to disable the automatic form that is generated around your comment prompt if you don't provide a =FORM= template. See [[Sandbox.CommentPluginExamples#noform][CommentPluginExamples:noform]] for an example. | =off= | 16 16 | =nopost= | Set to "on" to disable insertion of the posted text into the topic. | =off= | 17 17 | =remove= | Set to "on" to remove the comment prompt after the first time it is clicked. | =off= | -
trunk/CommentPlugin/lib/Foswiki/Plugins/CommentPlugin.pm
r8843 r8955 7 7 use strict; 8 8 use warnings; 9 use Assert; 10 use Error ':try'; 9 11 10 12 use Foswiki::Func (); … … 12 14 13 15 our $VERSION = '$Rev$'; 14 our $RELEASE = '31 Jul2010';16 our $RELEASE = '31 Aug 2010'; 15 17 our $SHORTDESCRIPTION = 16 18 'Quickly post comments to a page without an edit/save cycle'; 17 19 our $NO_PREFS_IN_TOPIC = 1; 18 20 21 # Reset when the plugin is reset, this counter counts the instances of the 22 # %COMMENT macro and indexes them. 23 our $commentIndex; 24 19 25 sub initPlugin { 20 26 21 #my ( $topic, $web, $user, $installWeb ) = @_; 27 my ( $topic, $web, $user, $installWeb ) = @_; 28 $commentIndex = 0; 29 30 Foswiki::Func::registerTagHandler('COMMENT', \&_COMMENT); 31 Foswiki::Func::registerRESTHandler('comment', \&_restSave); 32 33 if ((DEBUG) && $web eq $Foswiki::cfg{SystemWebName} 34 && $topic eq 'InstalledPlugins') { 35 # Compilation check 36 require Foswiki::Plugins::CommentPlugin::Comment; 37 } 22 38 return 1; 23 39 } 24 40 25 sub commonTagsHandler { 26 my ( $text, $topic, $web, $meta ) = @_; 27 41 sub _COMMENT { 42 my ( $session, $params, $topic, $web ) = @_; 43 44 # Indexing each macro instance 45 $params->{comment_index} = $commentIndex++; 46 47 # Check the context has 'view' script 48 my $context = Foswiki::Func::getContext(); 49 my $disabled = ''; 50 if ($context->{command_line}) { 51 $disabled = Foswiki::Func::expandCommonVariables( 52 '%MAKETEXT{"Commenting is disabled while running from the command line"}%'); 53 } elsif (!$context->{view}) { 54 $disabled = Foswiki::Func::expandCommonVariables( 55 '%MAKETEXT{"Commenting is disabled when not in view context"}%'); 56 } elsif (!($Foswiki::cfg{Plugins}{CommentPlugin}{GuestCanComment} 57 || $context->{authenticated})) { 58 $disabled = Foswiki::Func::expandCommonVariables( 59 '%MAKETEXT{"Commenting is disabled while not logged in"}%'); 60 } 61 28 62 require Foswiki::Plugins::CommentPlugin::Comment; 29 30 my $query = Foswiki::Func::getCgiQuery(); 31 return unless ( defined($query) ); 32 33 return unless $_[0] =~ m/%COMMENT({.*?})?%/o; 34 35 # SMELL: Nasty, tacky way to find out where we were invoked from 36 my $scriptname = $ENV{'SCRIPT_NAME'} || ''; 37 38 # SMELL: unreliable 39 my $previewing = ( $scriptname =~ /\/(preview|gnusave|rdiff|compare)/ ); 40 Foswiki::Plugins::CommentPlugin::Comment::prompt( $previewing, $_[0], $web, 41 $topic ); 63 64 Foswiki::Plugins::CommentPlugin::Comment::prompt( 65 $params, $web, $topic, $disabled ); 42 66 } 43 67 44 sub beforeSaveHandler { 68 # REST handler for save operator. We use a REST handler because we need 69 # to be able to bypass the permissions checking that the save script 70 # would do. We handle the return in several different ways; first, if 71 # everything is OK, we set a 200 status and drop back to allow any 72 # endPoint to be handled. Second, if we get an exception, and the 73 # 'comment_ajax' parameter is set, we return a 500 status. If the 74 # parameter is not set, we pass the exception on to the UI package. 45 75 46 #my ( $text, $topic, $web ) = @_; 76 sub _restSave { 77 my $session = shift; 78 my $response = $session->{response}; 79 my $query = Foswiki::Func::getCgiQuery(); 80 my ($web, $topic) = Foswiki::Func::normalizeWebTopicName( 81 undef, $query->param('topic')); 82 83 try { 84 require Foswiki::Plugins::CommentPlugin::Comment; 47 85 48 require Foswiki::Plugins::CommentPlugin::Comment;86 my ($meta, $text) = Foswiki::Func::readTopic($web, $topic); 49 87 50 my $query = Foswiki::Func::getCgiQuery(); 51 return unless $query; 52 53 my $action = $query->param('comment_action'); 54 55 return unless ( defined($action) && $action eq 'save' ); 56 57 # Stop it being applied again 58 $query->delete('comment_action'); 59 60 Foswiki::Plugins::CommentPlugin::Comment::save(@_); 88 # The save function does access control checking 89 $text = Foswiki::Plugins::CommentPlugin::Comment::save( 90 $text, $web, $topic); 91 92 Foswiki::Func::saveTopic($web, $topic, $meta, $text, 93 { ignorepermissions => 1 }); 94 95 $response->header(-status => 200); 96 $response->body("$web.$topic"); 97 } catch Foswiki::AccessControlException with { 98 if ($query->param('comment_ajax')) { 99 $response->header(-status => 404); 100 $response->body(shift); 101 } else { 102 shift->throw; 103 } 104 } otherwise { 105 if ($query->param('comment_ajax')) { 106 $response->header(-status => 500); 107 $response->body(shift); 108 } else { 109 shift->throw; 110 } 111 }; 112 return undef; 61 113 } 62 114 -
trunk/CommentPlugin/lib/Foswiki/Plugins/CommentPlugin/Comment.pm
r8843 r8955 5 5 use strict; 6 6 use warnings; 7 use Assert; 8 use Error ':try'; 7 9 8 10 use Foswiki; 9 11 use Foswiki::Plugins; 10 12 use Foswiki::Store; 11 use Foswiki::Attrs; 13 12 14 use CGI qw( -any ); 13 15 14 16 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 topic30 throw Foswiki::OopsException(31 'accessdenied',32 def => 'topic_access',33 web => $_[2],34 topic => $_[1]35 );36 }37 else {38 _buildNewTopic(@_);39 }40 }41 17 42 18 # PUBLIC STATIC convert COMMENT statements to form prompts 43 19 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 62 my $idx = 0; 63 $_[1] =~ 64 s/%COMMENT({.*?})?%/_handleInput($1,$_[2],$_[3],\$idx,$message,$disable,$defaultType)/eg; 65 } 66 67 =pod 68 69 Parses a templatetopic attribute and returns a "Web.Topic" string. 70 71 =cut 72 73 sub _getTemplateLocation { 74 my ( $attrtemplatetopic, $web ) = @_; 75 76 my $templatetopic = ''; 77 my $templateweb = $web || ''; 78 if ($attrtemplatetopic) { 20 my ( $attrs, $web, $topic, $disabled ) = @_; 21 22 my $type = $attrs->{type} || $attrs->{mode} 23 || Foswiki::Func::getPreferencesValue('COMMENTPLUGIN_DEFAULT_TYPE') 24 || 'above'; 25 26 my $templatetopic; 27 if ($attrs->{templatetopic}) { 79 28 my ( $templocweb, $temploctopic ) = 80 Foswiki::Func::normalizeWebTopicName( $templateweb,81 $attrtemplatetopic);29 Foswiki::Func::normalizeWebTopicName( 30 $web, $attrs->{templatetopic} ); 82 31 $templatetopic = "$templocweb.$temploctopic"; 83 32 } 84 return $templatetopic; 85 } 86 87 # PRIVATE generate an input form for a %COMMENT tag 88 sub _handleInput { 89 my ( $attributes, $web, $topic, $pidx, $message, $disable, $defaultType ) = 90 @_; 91 92 $attributes =~ s/^{(.*)}$/$1/ if ($attributes); 93 94 my $attrs = new Foswiki::Attrs( $attributes, 1 ); 95 my $type = $attrs->remove('type') || $attrs->remove('mode') || $defaultType; 96 my $silent = $attrs->remove('nonotify'); 97 my $location = $attrs->remove('location'); 98 my $remove = $attrs->remove('remove'); 99 my $nopost = $attrs->remove('nopost'); 100 my $default = $attrs->remove('default'); 101 my $attrtemplatetopic = $attrs->remove('templatetopic') || ''; 102 my $templatetopic = _getTemplateLocation( $attrtemplatetopic, $web ); 103 104 $message ||= $default || ''; 105 $message ||= $default || ''; 106 $disable ||= ''; 33 34 # Get the templates. 35 my $templateFile = 36 $templatetopic 37 || Foswiki::Func::getPreferencesValue('COMMENTPLUGIN_TEMPLATES') 38 || 'comments'; 39 40 unless( Foswiki::Func::loadTemplate($templateFile) ) { 41 Foswiki::Func::writeWarning( 42 "Could not read template file '$templateFile'"); 43 return _alert("Could not read templates from '$templateFile'"); 44 } 45 46 my $message = $attrs->{default} || ''; 47 $message = $disabled if $disabled; 107 48 108 49 # clean off whitespace 109 $type =~ m/(\S*)/; 110 $type = $1; 50 $type =~ s/\s+//; 111 51 112 52 # Expand the template in the context of the web where the comment 113 53 # box is (not the target of the comment!) 114 my $input = _getTemplate( "PROMPT:$type", $web, $topic, $templatetopic )115 || '';116 return $input if $input =~ m/^%RED%/so;54 my $input = Foswiki::Func::expandTemplate("PROMPT:$type"); 55 return _alert("No such template def 'PROMPT:$type'") 56 unless ( defined($input) && $input ne '' ); 117 57 118 58 # Expand special attributes as required 119 59 $input =~ s/%([a-z]\w+)\|(.*?)%/_expandPromptParams($1, $2, $attrs)/ieg; 60 61 # Build the endpoint before we munge the web and topic 62 my $endPoint = "$web.$topic"; 120 63 121 64 # see if this comment is targeted at a different topic, and 122 65 # change the url if it is. 123 66 my $anchor = undef; 124 my $target = $attrs-> remove('target');67 my $target = $attrs->{target}; 125 68 if ($target) { 126 69 … … 137 80 } 138 81 139 my $url = ''; 140 if ( $disable eq '' ) { 141 $url = Foswiki::Func::getScriptUrl( $web, $topic, 'save' ); 142 } 143 144 my $noform = $attrs->remove('noform') || ''; 82 # See if a save url has been defined in the template 83 my $url = Foswiki::Func::expandTemplate('save_url'); 84 85 # Default it to a rest url if not 86 $url ||= Foswiki::Func::getScriptUrl('CommentPlugin', 'comment', 'rest' ); 87 88 $url = '' if $disabled; 89 90 my $noform = $attrs->{noform} || ''; 145 91 if ( $input !~ m/^%RED%/ ) { 146 $input =~ s/%DISABLED%/$disable /g;92 $input =~ s/%DISABLED%/$disabled ? 'disabled' : '' /ge; 147 93 $input =~ s/%MESSAGE%/$message/g; 148 my $ n = $$pidx + 0;149 150 if ( $disable eq '') {94 my $idx = $attrs->{comment_index}; 95 96 unless( $disabled ) { 151 97 my $hiddenFields = ""; 152 98 $hiddenFields .= 153 "\n" . CGI::hidden( -name => 'comment_action', -value => 'save' ); 99 CGI::hidden( -name => 'topic', -value => "$web.$topic"); 100 154 101 $hiddenFields .= 155 "\n" . CGI::hidden( -name => 'comment_type', -value => $type ); 156 if ( defined($silent) ) { 157 $hiddenFields .= 158 "\n" . CGI::hidden( -name => 'comment_nonotify', value => 1 ); 102 CGI::hidden( -name => 'comment_action', -value => 'save' ); 103 104 $hiddenFields .= 105 CGI::hidden( -name => 'endPoint', -value => $endPoint ); 106 107 $hiddenFields .= 108 CGI::hidden( -name => 'comment_type', -value => $type ); 109 110 if ( defined($attrs->{nonotify}) ) { 111 $hiddenFields .= 112 CGI::hidden( -name => 'comment_nonotify', value => 1 ); 159 113 } 160 114 if ($templatetopic) { 161 $hiddenFields .= "\n"162 .CGI::hidden(163 -name => 'comment_templatetopic',164 -value => $templatetopic165 );166 } 167 if ($ location) {168 $hiddenFields .= "\n"169 .CGI::hidden(170 -name => 'comment_location',171 -value => $location172 );115 $hiddenFields .= 116 CGI::hidden( 117 -name => 'comment_templatetopic', 118 -value => $templatetopic 119 ); 120 } 121 if ($attrs->{location}) { 122 $hiddenFields .= 123 CGI::hidden( 124 -name => 'comment_location', 125 -value => $attrs->{location} 126 ); 173 127 } 174 128 elsif ($anchor) { 175 $hiddenFields .= "\n"176 .CGI::hidden( -name => 'comment_anchor', -value => $anchor );129 $hiddenFields .= 130 CGI::hidden( -name => 'comment_anchor', -value => $anchor ); 177 131 } 178 132 else { 179 $hiddenFields .= "\n" 180 . CGI::hidden( -name => 'comment_index', -value => $$pidx ); 181 } 182 if ($nopost) { 183 $hiddenFields .= "\n" 184 . CGI::hidden( -name => 'comment_nopost', -value => $nopost ); 185 } 186 if ($remove) { 187 $hiddenFields .= "\n" 188 . CGI::hidden( -name => 'comment_remove', -value => $$pidx ); 133 $hiddenFields .= 134 CGI::hidden( -name => 'comment_index', -value => $idx ); 135 } 136 if ($attrs->{nopost}) { 137 $hiddenFields .= 138 CGI::hidden( -name => 'comment_nopost', 139 -value => $attrs->{nopost} ); 140 } 141 if ($attrs->{remove}) { 142 $hiddenFields .= 143 CGI::hidden( -name => 'comment_remove', -value => $idx ); 189 144 } 190 145 $input .= $hiddenFields; 191 146 } 192 if ($noform) { 193 my $form = 194 _getTemplate( "FORM:$type", $topic, $web, $templatetopic, 'off' ) 195 || ''; 147 148 # SMELL: would have been more elegant to split this into 149 # FORM:head:type and FORM:tail:type. Too late now :-( 150 my $form = Foswiki::Func::expandTemplate("FORM:$type"); 151 152 if ( $noform || $form) { 196 153 if ($form) { 197 154 $form =~ s/%COMMENTPROMPT%/$input/; 198 155 $input = $form; 199 } 200 } 201 unless ( $noform eq 'on' ) { 156 } else { 157 $input = "NOFORM $form $input"; 158 } 159 } else { 202 160 $input = CGI::start_form( 203 -name => $type . $ n,204 -id => $type . $ n,161 -name => $type . $idx, 162 -id => $type . $idx, 205 163 -action => $url, 206 164 -method => 'post' 207 )165 ) 208 166 . $input 209 . CGI::end_form(); 210 } 211 } 212 $$pidx++; 167 . CGI::end_form(); 168 } 169 } 213 170 return $input; 214 171 } 215 172 216 # PRIVATE get the given template and do standard expansions 217 sub _getTemplate { 218 my ( $name, $topic, $web, $templatetopic, $warn ) = @_; 219 220 $warn ||= ''; 221 222 # Get the templates. 223 my $templateFile = 224 $templatetopic 225 || Foswiki::Func::getPreferencesValue('COMMENTPLUGIN_TEMPLATES') 226 || 'comments'; 227 228 my $templates = Foswiki::Func::loadTemplate($templateFile); 229 if ( !$templates ) { 230 Foswiki::Func::writeWarning( 231 "Could not read template file '$templateFile'"); 232 return; 233 } 234 235 my $t = Foswiki::Func::expandTemplate($name); 236 return "%RED%No such template def TMPL:DEF{$name}%ENDCOLOR%" 237 unless ( defined($t) && $t ne '' ) || $warn eq 'off'; 238 239 return $t; 173 sub _alert { 174 my $mess = shift; 175 return "<span class='foswikiAlert'> $mess </span>"; 240 176 } 241 177 … … 249 185 } 250 186 251 # PRIVATE STATIC Performs comment insertion in the topic. 252 sub _buildNewTopic { 253 254 #my ( $text, $topic, $web ) = @_; 255 my ( $topic, $web ) = ( $_[1], $_[2] ); 187 # PUBLIC build new topic text 188 sub save { 189 190 my ( $text, $web, $topic ) = @_; 191 192 my $wikiName = Foswiki::Func::getWikiName(); 193 my $mode = $Foswiki::cfg{Plugins}{CommentPlugin}{RequiredForSave} 194 || 'change'; 195 my $access = Foswiki::Func::checkAccessPermission( 196 $mode, $wikiName, $text, $topic, $web); 197 unless ($access) { 198 # user has no permission to change the topic 199 throw Foswiki::AccessControlException( 200 $mode, 201 $wikiName, 202 web => $web, 203 topic => $topic, 204 '' ); 205 } 256 206 257 207 my $query = Foswiki::Func::getCgiQuery(); 258 208 return unless $query; 259 209 210 # The type of the comment dictates where in the target topic it 211 # will be saved. 260 212 my $type = 261 $query->param('comment_type') 262 || Foswiki::Func::getPreferencesValue('COMMENTPLUGIN_DEFAULT_TYPE') 263 || 'above'; 213 $query->param('comment_type') 214 || Foswiki::Func::getPreferencesValue('COMMENTPLUGIN_DEFAULT_TYPE') 215 || 'above'; 216 217 # Indexing comment instances depends on macro expansion 218 # inside-out-left-right order and INCLUDE and SECTION expansion 219 # being correctly handled. Only relevant if the comment is being 220 # inserted relative to the instance, of course. 264 221 my $index = $query->param('comment_index') || 0; 222 265 223 my $anchor = $query->param('comment_anchor'); 266 224 my $location = $query->param('comment_location'); 267 225 my $remove = $query->param('comment_remove'); 268 226 my $nopost = $query->param('comment_nopost'); 269 my $templatetopic = $query->param('comment_templatetopic') || ''; 270 271 my $output = _getTemplate( "OUTPUT:$type", $topic, $web, $templatetopic ); 272 if ( $output =~ m/^%RED%/ ) { 273 die $output; 274 } 227 my $templatetopic = $query->param('comment_templatetopic'); 228 229 if ($templatetopic) { 230 my ( $templocweb, $temploctopic ) = 231 Foswiki::Func::normalizeWebTopicName( 232 $web, $templatetopic ); 233 $templatetopic = "$templocweb.$temploctopic"; 234 } 235 236 # Get the templates. 237 my $templateFile = 238 $templatetopic 239 || Foswiki::Func::getPreferencesValue('COMMENTPLUGIN_TEMPLATES') 240 || 'comments'; 241 242 Foswiki::Func::loadTemplate($templateFile); 243 244 my $output = Foswiki::Func::expandTemplate("OUTPUT:$type"); 245 die _alert("No such template def 'OUTPUT:$type'") unless $output; 275 246 276 247 # Expand the template … … 290 261 # methods in the core. Fortunately this will work even if there is 291 262 # no embedded meta-data. 292 # Note: because this is Dakar, and has sensible semantics for handling293 # the =text= parameter to =save=, there is no longer any need to re-read294 # the topic. The text is automatically defaulted to the existing topic295 # text if the =text= parameter isn't specified - which for comments,296 # it isn't.297 263 my $premeta = ''; 298 264 my $postmeta = ''; 299 265 my $inpost = 0; 300 my $ text = '';301 foreach my $line ( split( /\r?\n/, $ _[0]) ) {302 if ( $line =~ /^%META:[A-Z]+{[^}]*}% / ) {266 my $innerText = ''; 267 foreach my $line ( split( /\r?\n/, $text ) ) { 268 if ( $line =~ /^%META:[A-Z]+{[^}]*}%$/ ) { 303 269 if ($inpost) { 304 270 $postmeta .= $line . "\n"; … … 309 275 } 310 276 else { 311 $ text .= $line . "\n";277 $innerText .= $line . "\n"; 312 278 $inpost = 1; 313 279 } 314 280 } 281 $text = $innerText; 315 282 316 283 #make sure the anchor or location exits … … 390 357 } 391 358 392 $_[0] =$premeta . $text . $postmeta;359 return $premeta . $text . $postmeta; 393 360 } 394 361 -
trunk/CommentPlugin/lib/Foswiki/Plugins/CommentPlugin/Config.spec
r8837 r8955 16 16 # a comment is saved. 17 17 $Foswiki::cfg{Plugins}{CommentPlugin}{GuestCanComment} = 1; 18 # ---+ Extensions 19 # ---++ CommentPlugin 20 # **SELECT CHANGE,COMMENT** 21 # Access control permissions that are required to be able to add a comment 22 # to a topic. CHANGE is the default, the same as for an adit, but you can 23 # also select COMMENT which will check e.g. ALLOWTOPICCOMMENT. This lets you 24 # grant users COMMENT access without giving them open access to edit the 25 # topic. <strong>Note</strong>Foswiki 1.1 and later only. This feature is 26 # not supported when the plugin is installed in earlier releases. These 27 # releases require CHANGE permission on all writable topics. 28 $Foswiki::cfg{Plugins}{CommentPlugin}{RequiredForSave} = 'CHANGE'; 29 # **BOOLEAN** 30 # If this option is disabled, the guest user will not be offered the 31 # comment prompt *even if access controls permit them to save*. Note that 32 # even if this option is true, access controls will still be checked when 33 # a comment is saved. 34 $Foswiki::cfg{Plugins}{CommentPlugin}{GuestCanComment} = 1; -
trunk/CommentPlugin/lib/Foswiki/Plugins/CommentPlugin/MANIFEST
r8843 r8955 1 !noci 1 2 data/System/CommentPlugin.txt 0644 Plugin doc page 2 3 data/System/VarCOMMENT.txt 0644 Comment tag doc page … … 8 9 lib/Foswiki/Plugins/CommentPlugin.pm 0444 Plugin Perl module 9 10 lib/Foswiki/Plugins/CommentPlugin/Comment.pm 0444 Plugin Perl module 10 11 lib/Foswiki/Plugins/CommentPlugin/Config.spec 0444 Configuration module 11 12 pub/System/CommentPlugin/wikiringlogo20x20.png 0660 13 pub/System/CommentPlugin/comment_src.js 0660 -
trunk/CommentPlugin/pub/System/CommentPlugin/comment_src.js
r8837 r8955 1 /* 2 Foswiki - The Free and Open Source Wiki, http://foswiki.org/ 3 4 Copyright (C) 2010 Foswiki Contributors. Foswiki Contributors 5 are listed in the AUTHORS file in the root of this distribution. 6 NOTE: Please extend that file, not this notice. 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2 11 of the License, or (at your option) any later version. For 12 more details read LICENSE in the root of this distribution. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17 18 As per the GPL, removal of this notice is prohibited. 19 20 This is an example of a simple AJAX comment submission. 21 22 */ 23 (function($) { 24 $(document).ready( 25 function() { 26 $("textarea.commentPluginAjax") 27 .blur( 28 function() { 29 if (this.value == '') 30 this.value = this.title; 31 }) 32 .focus( 33 function() { 34 if (this.value == this.title) 35 this.value = ''; 36 }) 37 .keypress( 38 function() { 39 var form = $(this).parents("form")[0]; 40 $(form).find(".commentPluginStatusResponse").html(''); 41 }); 42 $("input.commentPluginAjax").click( 43 function(e) { 44 var form = $(this).parents("form")[0]; 45 // Remove the endpoint; we want a status report 46 $(form).find("input[name='endPoint']").remove(); 47 $.post(form.action, $(form).serialize(), 48 function() { 49 // Fake the format of the comment that was 50 // added to the topic 51 $(form).before( 52 "<p/>" + $(form).find( 53 "textarea.commentPluginAjax").text() 54 + "<p />-- " 55 + foswiki.getPreference("WIKINAME")); 56 }); 57 }); 58 }); 59 })(jQuery); 1 60 /* 2 61 Foswiki - The Free and Open Source Wiki, http://foswiki.org/ -
trunk/CommentPlugin/test/unit/CommentPlugin/CommentPluginTests.pm
r8843 r8955 7 7 use FoswikiFnTestCase; 8 8 our @ISA = qw( FoswikiFnTestCase ); 9 use Error ':try'; 9 10 10 11 use Unit::Request; … … 27 28 $webObject->populateNewWeb(); 28 29 30 Foswiki::Func::getContext()->{view} = 1; 31 $Foswiki::cfg{Plugins}{CommentPlugin}{RequiredForSave} = 'CHANGE'; 32 $Foswiki::cfg{Plugins}{CommentPlugin}{GuestCanComment} = 1; 33 29 34 return; 30 35 } … … 64 69 my ( $this, $type, $web, $topic, $anchor, $location ) = @_; 65 70 66 my $eidx = 1;71 my $eidx = $Foswiki::Plugins::CommentPlugin::commentIndex; 67 72 my $sattrs = ""; 68 73 … … 70 75 $topic ||= $this->{test_topic}; 71 76 72 if ( $web ne $this->{test_web} || $topic ne $this->{test_topic} || $anchor ) 77 if ( $web ne $this->{test_web} || $topic ne $this->{test_topic} 78 || $anchor ) 73 79 { 74 80 … … 85 91 } 86 92 87 my $url = Foswiki::Func::getScriptUrl( $web, $topic, 'save' );93 my $url = Foswiki::Func::getScriptUrl( 'CommentPlugin', 'comment', 'rest' ); 88 94 89 95 if ($location) { … … 94 100 $sattrs .= 'type="' . $type . '" '; 95 101 96 my $commentref = '%COMMENT{' . $sattrs . ' refmark="here"}%'; 102 my $commentref = '%COMMENT{' . $sattrs . 103 ' refmark="here" default="The Message"}%'; 97 104 98 105 # Build the target topic 99 106 my $sample = <<"HERE"; 100 107 TopOfTopic 101 %COMMENT{$sattrs}% 108 $commentref 102 109 HERE 103 110 if ($anchor) { … … 116 123 HERE 117 124 118 $this->writeTopic( $web, $topic, $sample ); 119 my $pidx = $eidx; 120 my $html = 121 Foswiki::Plugins::CommentPlugin::Comment::_handleInput( $sattrs, 122 $this->{test_web}, $this->{test_topic}, \$pidx, "The Message", "", 123 "bottom" ); 125 Foswiki::Func::saveTopic( $web, $topic, undef, $sample ); 126 127 my $html = Foswiki::Func::expandCommonVariables($commentref); 124 128 125 129 $html = removeEscapes($html); 126 $this->assert( $pidx == $eidx + 1, $html ); 127 128 $this->assert( scalar( $html =~ s/^<form(.*?)>//sio ) ); 130 131 $this->assert( scalar( $html =~ s/^<form(.*?)>//sio ), $html ); 129 132 my $dattrs = $1; 130 133 $this->assert( scalar( $html =~ s/<\/form>\s*$//sio ) ); … … 137 140 $dattrs =~ s#application/x-www-form-urlencoded#multipart/form-data#; 138 141 $this->assert_str_equals( 139 'enctype="multipart/form-data" id="' . $type . ' 1"',142 'enctype="multipart/form-data" id="' . $type . '0"', 140 143 trim($dattrs) ); 141 144 … … 216 219 'comment_type' => $type, 217 220 'comment' => $comm, 218 } 219 ); 220 $query->path_info("/$web/$topic"); 221 'topic' => "$web.$topic", 222 } 223 ); 224 $query->path_info("/CommentPlugin/comment"); 221 225 if ($anchor) { 222 226 $query->param( -name => 'comment_anchor', -value => $anchor ); … … 229 233 } 230 234 231 my $session = Foswiki->new( $Foswiki::cfg{DefaultUserLogin Name}, $query );235 my $session = Foswiki->new( $Foswiki::cfg{DefaultUserLogin}, $query ); 232 236 my $text = "Ignore this text"; 233 237 234 238 # invoke the save handler 235 $this->captureWithKey( save => $this->getUIFn('save'), $session );239 $this->captureWithKey( rest => $this->getUIFn('rest'), $session ); 236 240 237 241 $text = Foswiki::Func::readTopicText( $web, $topic ); … … 340 344 # id: This gives a unique name for a COMMENT, in case you have more than one COMMENT tag in a topic (mandatory with > 1 COMMENT) 341 345 342 my $pidx = 0; 343 my $html = Foswiki::Plugins::CommentPlugin::Comment::_handleInput( 344 "rows=99 cols=104 mode=after button=HoHo id=sausage", 345 , $this->{test_topic}, $this->{test_web}, \$pidx, "The Message", "", 346 "bottom" ); 346 my $comment = '%COMMENT{type="after" rows="99" cols="104" mode="after" button="HoHo" id="sausage"}%'; 347 my $html = Foswiki::Func::expandCommonVariables( $comment ); 347 348 $html = removeEscapes($html); 348 349 $this->assert_matches( qr/form [^>]*name=\"after0\"/, $html ); … … 356 357 sub test_locationOverridesAnchor { 357 358 my $this = shift; 358 my $pidx = 0; 359 my $html = Foswiki::Plugins::CommentPlugin::Comment::_handleInput( 360 "target=\"$this->{test_web}.ATopic#AAnchor\" location=\"AnRE\"", 361 $this->{test_topic}, 362 $this->{test_web}, 363 \$pidx, 364 "The Message", 365 "", 366 "bottom" 367 ); 359 my $html = Foswiki::Func::expandCommonVariables("%COMMENT{type=\"bottom\" target=\"$this->{test_web}.ATopic#AAnchor\" location=\"AnRE\"}%"); 360 368 361 $this->assert_matches( qr/<input ([^>]*name="comment_location".*?)\s*\/>/, 369 362 $html ); … … 380 373 after 381 374 HERE 382 $this->writeTopic( $this->{test_web}, $this->{test_topic}, $sample );383 my $pidx = 0;375 Foswiki::Func::saveTopic( 376 $this->{test_web}, $this->{test_topic}, undef, $sample ); 384 377 my $html = 385 Foswiki::Plugins::CommentPlugin::Comment::_handleInput( 'nopost="on"', 386 $this->{test_web}, $this->{test_topic}, \$pidx, "The Message", "", 387 "bottom" ); 378 Foswiki::Func::expandCommonVariables( '%COMMENT{nopost="on"}%'); 379 388 380 $this->assert_matches( 389 381 qr/<input type="hidden" name="comment_nopost" value="on"/, $html ); … … 397 389 'comment' => $comm, 398 390 'comment_nopost' => 'on', 399 } 400 ); 401 $query->path_info("/$this->{test_web}/$this->{test_topic}"); 402 403 my $session = Foswiki->new( $Foswiki::cfg{DefaultUserLoginName}, $query ); 391 'topic' => "$this->{test_web}.$this->{test_topic}" 392 } 393 ); 394 $query->path_info("/CommentPlugin/comment"); 395 396 my $session = Foswiki->new( $Foswiki::cfg{DefaultUserLogin}, $query ); 404 397 my $text = "Ignore this text"; 405 398 406 399 # invoke the save handler 407 $this->captureWithKey( save => $this->getUIFn('save'), $session );400 $this->captureWithKey( rest => $this->getUIFn('rest'), $session ); 408 401 409 402 $text = … … 425 418 after 426 419 HERE 427 $this->writeTopic( $this->{test_web}, $this->{test_topic}, $sample );428 my $pidx = 99;420 Foswiki::Func::saveTopic( 421 $this->{test_web}, $this->{test_topic}, undef, $sample ); 429 422 my $html = 430 Foswiki::Plugins::CommentPlugin::Comment::_handleInput( 'remove="on"', 431 $this->{test_web}, $this->{test_topic}, \$pidx, "The Message", "", 432 "bottom" ); 423 Foswiki::Func::expandCommonVariables( '%COMMENT{remove="on"}%'); 424 433 425 $this->assert_matches( 434 qr/<input type="hidden" name="comment_remove" value=" 99"/, $html );426 qr/<input type="hidden" name="comment_remove" value="0"/, $html ); 435 427 436 428 # Compose the query … … 443 435 'comment_remove' => '0', 444 436 'comment_index' => '99', 445 } 446 ); 447 $query->path_info("/$this->{test_web}/$this->{test_topic}"); 448 449 my $session = Foswiki->new( $Foswiki::cfg{DefaultUserLoginName}, $query ); 437 'topic' => "$this->{test_web}/$this->{test_topic}", 438 } 439 ); 440 $query->path_info("/CommentPlugin/comment"); 441 442 my $session = Foswiki->new( $Foswiki::cfg{DefaultUserLogin}, $query ); 450 443 my $text = "Ignore this text"; 451 444 452 445 # invoke the save handler 453 $this->captureWithKey( save => $this->getUIFn('save'), $session );446 $this->captureWithKey( rest => $this->getUIFn('rest'), $session ); 454 447 455 448 $text = … … 477 470 after 478 471 HERE 479 $this->writeTopic( $this->{test_web}, $this->{test_topic}, $sample ); 480 my $pidx = 99; 481 my $html = Foswiki::Plugins::CommentPlugin::Comment::_handleInput( 482 'default="wibble"', $this->{test_web}, $this->{test_topic}, \$pidx, 483 undef, "", "bottom" ); 472 Foswiki::Func::saveTopic( 473 $this->{test_web}, $this->{test_topic}, undef, $sample ); 474 my $html = Foswiki::Func::expandCommonVariables('%COMMENT{default="wibble"}%'); 475 484 476 $this->assert_matches( qr#>wibble</textarea>#, $html ); 485 477 … … 495 487 after 496 488 HERE 497 $this->writeTopic( $this->{test_web}, $this->{test_topic}, $sample );498 my $pidx = 99;489 Foswiki::Func::saveTopic( 490 $this->{test_web}, $this->{test_topic}, undef, $sample ); 499 491 my $html = 500 Foswiki::Plugins::CommentPlugin::Comment::_handleInput( 'remove="on"', 501 $this->{test_web}, $this->{test_topic}, \$pidx, "The Message", "", 502 "bottom" ); 492 Foswiki::Func::expandCommonVariables( '%COMMENT{remove="on"}%'); 493 503 494 $this->assert_matches( 504 qr/<input type="hidden" name="comment_remove" value=" 99"/, $html );495 qr/<input type="hidden" name="comment_remove" value="0"/, $html ); 505 496 506 497 # Compose the query … … 512 503 'comment' => $comm, 513 504 'comment_anchor' => '#LatestComment', 514 } 515 ); 516 $query->path_info("/$this->{test_web}/$this->{test_topic}"); 517 518 my $session = Foswiki->new( $Foswiki::cfg{DefaultUserLoginName}, $query ); 505 'topic' => "$this->{test_web}.$this->{test_topic}", 506 } 507 ); 508 $query->path_info("/CommentPlugin/comment"); 509 510 my $session = Foswiki->new( $Foswiki::cfg{DefaultUserLogin}, $query ); 519 511 my $text = "Ignore this text"; 520 512 521 513 # invoke the save handler 522 $this->captureWithKey( save => $this->getUIFn('save'), $session );514 $this->captureWithKey( rest => $this->getUIFn('rest'), $session ); 523 515 524 516 $text = … … 551 543 after 552 544 HERE 553 $this->writeTopic( $this->{test_web}, $this->{test_topic}, $sample );554 my $pidx = 99;545 Foswiki::Func::saveTopic( 546 $this->{test_web}, $this->{test_topic}, undef, $sample ); 555 547 my $html = 556 Foswiki::Plugins::CommentPlugin::Comment::_handleInput( 'remove="on"', 557 $this->{test_web}, $this->{test_topic}, \$pidx, "The Message", "", 558 "bottom" ); 548 Foswiki::Func::expandCommonVariables( '%COMMENT{remove="on"}%'); 549 559 550 $html = removeEscapes($html); 560 551 $this->assert_matches( 561 qr/<input type="hidden" name="comment_remove" value=" 99"/, $html );552 qr/<input type="hidden" name="comment_remove" value="0"/, $html ); 562 553 563 554 # Compose the query … … 569 560 'comment' => $comm, 570 561 'comment_anchor' => '#LatestComment', 571 572 } 573 ); 574 $query->path_info("/ $this->{test_web}/$this->{test_topic}");575 576 my $session = Foswiki->new( $Foswiki::cfg{DefaultUserLogin Name}, $query );562 'topic' => "$this->{test_web}.$this->{test_topic}", 563 } 564 ); 565 $query->path_info("/CommentPlugin/comment"); 566 567 my $session = Foswiki->new( $Foswiki::cfg{DefaultUserLogin}, $query ); 577 568 my $text = "Ignore this text"; 578 569 579 570 # invoke the save handler 580 $this->captureWithKey( save => $this->getUIFn('save'), $session );571 $this->captureWithKey( rest => $this->getUIFn('rest'), $session ); 581 572 582 573 $text = … … 600 591 } 601 592 593 sub test_acl_COMMENT { 594 my $this = shift; 595 596 my $sample = <<HERE; 597 * Set DENYTOPICCHANGE = $Foswiki::cfg{DefaultUserWikiName} 598 * Set DENYTOPICVIEW = $Foswiki::cfg{DefaultUserWikiName} 599 * Set ALLOWTOPICCOMMENT = $Foswiki::cfg{DefaultUserWikiName} 600 %COMMENT% 601 HERE 602 Foswiki::Func::saveTopic( 603 $this->{test_web}, $this->{test_topic}, undef, $sample ); 604 605 # Compose the query 606 my $comm = "This is the comment"; 607 my $query = Unit::Request->new( 608 { 609 'comment_action' => 'save', 610 'comment_type' => 'above', 611 'comment' => $comm, 612 topic => "$this->{test_web}.$this->{test_topic}", 613 } 614 ); 615 $query->path_info("/CommentPlugin/comment"); 616 617 $Foswiki::cfg{Plugins}{CommentPlugin}{RequiredForSave} = 'CHANGE'; 618 619 my ($responseText, $result, $stdout, $stderr, $session); 620 # First make sure we can't *change* it 621 $session = Foswiki->new( $Foswiki::cfg{DefaultUserLogin}, $query ); 622 623 # invoke the save handler 624 625 eval { 626 ($responseText, $result, $stdout, $stderr) = 627 $this->captureWithKey( rest => $this->getUIFn('rest'), $session ); 628 }; 629 630 $this->assert($@); 631 $this->assert_matches(qr"OopsException\(accessdenied/topic_access", $@); 632 633 # Now make sure we *can* change it, given COMMENT access 634 $Foswiki::cfg{Plugins}{CommentPlugin}{RequiredForSave} = 'COMMENT'; 635 636 $session = Foswiki->new( $Foswiki::cfg{DefaultUserLogin}, $query ); 637 638 # invoke the save handler 639 ($responseText, $result, $stdout, $stderr) = 640 $this->captureWithKey( rest => $this->getUIFn('rest'), $session ); 641 $this->assert_matches(qr/Status: 200/, $responseText); 642 643 my ( $meta, $text ) = 644 Foswiki::Func::readTopic( $this->{test_web}, $this->{test_topic} ); 645 $text =~ s/- \d\d [A-Z][a-z]{2} \d{4}/- DATE/; 646 $this->assert_str_equals(<<HERE, $text); 647 * Set DENYTOPICCHANGE = WikiGuest 648 * Set DENYTOPICVIEW = $Foswiki::cfg{DefaultUserWikiName} 649 * Set ALLOWTOPICCOMMENT = WikiGuest 650 651 652 This is the comment 653 654 -- TemporaryCommentPluginTestsUsersWeb.WikiGuest - DATE 655 %COMMENT% 656 HERE 657 } 658 659 sub test_rest_control_modes { 660 my $this = shift; 661 my $sample = <<HERE; 662 * Set DENYTOPICCHANGE = $Foswiki::cfg{DefaultUserWikiName} 663 %COMMENT% 664 HERE 665 Foswiki::Func::saveTopic( 666 $this->{test_web}, $this->{test_topic}, undef, $sample ); 667 668 # other tests have already covered the non-ajax, no endpoint mode 669 my $query = Unit::Request->new( 670 { 671 'comment_action' => 'save', 672 'comment_type' => 'above', 673 'comment' => "Arfle barfle gloop", 674 'comment_ajax' => 1, 675 topic => "$this->{test_web}.$this->{test_topic}", 676 } 677 ); 678 $query->path_info("/CommentPlugin/comment"); 679 my ($responseText, $result, $stdout, $stderr); 680 my $session = new Foswiki(undef, $query); 681 eval { 682 ($responseText, $result, $stdout, $stderr) = 683 $this->captureWithKey( rest => $this->getUIFn('rest'), $session ); 684 }; 685 $this->assert_matches(qr/Status: 404/, $responseText); 686 687 } 688 602 689 1; 603 690 __END__
Note: See TracChangeset
for help on using the changeset viewer.
