1 # Plugin for TWiki Enterprise Collaboration Platform, http://TWiki.org/
3 # Copyright (C) 2005-2007 TWiki Contributors.
4 # All Rights Reserved. TWiki Contributors are listed in the
5 # AUTHORS file in the root of this distribution.
6 # NOTE: Please extend that file, not this notice.
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.
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.
18 # For licensing info read LICENSE file in the TWiki root.
21 # Handle continuation lines (see Prefs::parseText). These should always
22 # go into a text area.
24 package TWiki::Plugins::PreferencesPlugin;
28 require TWiki::Func; # The plugins API
29 require TWiki::Plugins; # For the API version
31 use vars qw( $VERSION $RELEASE @shelter );
33 # This should always be $Rev: 15487 (22 Jan 2008) $ so that TWiki can determine the checked-in
34 # status of the plugin. It is used by the build automation tools, so
35 # you should leave it alone.
36 $VERSION = '$Rev: 15487 (22 Jan 2008) $';
38 # This is a free-form string you can use to "name" your own plugin version.
39 # It is *not* used by the build automation tools, but is reported as part
40 # of the version number in PLUGINDESCRIPTIONS.
41 $RELEASE = 'TWiki-4.2';
45 # Markers used during form generation
46 my $START_MARKER = $MARKER.'STARTPREF'.$MARKER;
47 my $END_MARKER = $MARKER.'ENDPREF'.$MARKER;
50 # check for Plugins.pm versions
51 if( $TWiki::Plugins::VERSION < 1.026 ) {
52 TWiki::Func::writeWarning( 'Version mismatch between PreferencesPlugin and Plugins.pm' );
60 sub beforeCommonTagsHandler {
61 ### my ( $text, $topic, $web ) = @_;
64 return unless ( $_[0] =~ m/%EDITPREFERENCES(?:{(.*?)})?%/ );
69 my $attrs = new TWiki::Attrs( $1 );
70 if( defined( $attrs->{_DEFAULT} )) {
71 my( $formWeb, $form ) = TWiki::Func::normalizeWebTopicName(
72 $web, $attrs->{_DEFAULT} );
74 # SMELL: Unpublished API. No choice, though :-(
75 require TWiki::Form; # SMELL
77 new TWiki::Form( $TWiki::Plugins::SESSION, $formWeb, $form );
80 my $query = TWiki::Func::getCgiQuery();
82 my $action = lc $query->param( 'prefsaction' );
83 $query->Delete( 'prefsaction' );
86 if ( $action eq 'edit' ) {
87 TWiki::Func::setTopicEditLock( $web, $topic, 1 );
89 # Replace setting values by form fields but not inside comments Item4816
91 my $insidecomment = 0;
92 foreach my $token ( split/(<!--|-->)/, $_[0] ) {
93 if ( $token =~ /<!--/ ) {
95 } elsif ( $token =~ /-->/ ) {
96 $insidecomment-- if ( $insidecomment > 0 );
97 } elsif ( !$insidecomment ) {
98 $token =~ s(^((?:\t| )+\*\sSet\s*)(\w+)\s*\=(.*$(\n[ \t]+[^\s*].*$)*))
99 ($1._generateEditField($web, $topic, $2, $3, $formDef))gem;
105 $_[0] =~ s/%EDITPREFERENCES({.*?})?%/
106 _generateControlButtons($web, $topic)/ge;
107 my $viewUrl = TWiki::Func::getScriptUrl(
108 $web, $topic, 'viewauth' );
109 my $startForm = CGI::start_form(
110 -name => 'editpreferences',
112 -action => $viewUrl );
113 $startForm =~ s/\s+$//s;
114 my $endForm = CGI::end_form();
115 $endForm =~ s/\s+$//s;
116 $_[0] =~ s/^(.*?)$START_MARKER(.*)$END_MARKER(.*?)$/$1$startForm$2$endForm$3/s;
117 $_[0] =~ s/$START_MARKER|$END_MARKER//gs;
120 if( $action eq 'cancel' ) {
121 TWiki::Func::setTopicEditLock( $web, $topic, 0 );
123 } elsif( $action eq 'save' ) {
125 my( $meta, $text ) = TWiki::Func::readTopic( $web, $topic );
126 $text =~ s(^((?:\t| )+\*\sSet\s)(\w+)\s\=\s(.*)$)
127 ($1._saveSet($query, $web, $topic, $2, $3, $formDef))mgeo;
128 TWiki::Func::saveTopic( $web, $topic, $meta, $text );
129 TWiki::Func::setTopicEditLock( $web, $topic, 0 );
130 # Finish with a redirect so that the *new* values are seen
131 my $viewUrl = TWiki::Func::getScriptUrl( $web, $topic, 'view' );
132 TWiki::Func::redirectCgiQuery( undef, $viewUrl );
135 # implicit action="view", or drop through from "save" or "cancel"
136 $_[0] =~ s/%EDITPREFERENCES({.*?})?%/_generateEditButton($web, $topic)/ge;
139 # Use the post-rendering handler to plug our formatted editor units
141 sub postRenderingHandler {
142 ### my ( $text ) = @_;
144 $_[0] =~ s/SHELTER$MARKER(\d+)/$shelter[$1]/g;
147 # Pluck the default value of a named field from a form definition
149 my( $formDef, $name ) = @_;
150 foreach my $f ( @{$formDef->{fields}} ) {
151 if( $f->{name} eq $name ) {
158 # Generate a field suitable for editing this type. Use of the core
159 # function 'renderFieldForEdit' ensures that we will pick up
160 # extra edit types defined in other plugins.
161 sub _generateEditField {
162 my( $web, $topic, $name, $value, $formDef ) = @_;
163 $value =~ s/^\s*(.*?)\s*$/$1/ge;
169 if (defined(&TWiki::Form::getField)) {
170 # TWiki 4.2 and later
171 $fieldDef = $formDef->getField( $name );
174 $fieldDef = _getField( $formDef, $name );
177 if( defined(&TWiki::Form::renderFieldForEdit)) {
178 # TWiki < 4.2 SMELL: use of unpublished core function
180 $formDef->renderFieldForEdit( $fieldDef, $web, $topic, $value);
182 # TWiki 4.2 and later SMELL: use of unpublished core function
184 $fieldDef->renderForEdit( $web, $topic, $value );
189 # No form definition, default to text field.
190 $html = CGI::textfield( -class=>'twikiEditFormError twikiInputField',
192 -size => 80, -value => $value );
195 push( @shelter, $html );
197 return $START_MARKER.
198 CGI::span({class=>'twikiAlert',
199 style=>'font-weight:bold;'},
200 $name . ' = SHELTER' . $MARKER . $#shelter).$END_MARKER;
203 # Generate the button that replaces the EDITPREFERENCES tag in view mode
204 sub _generateEditButton {
205 my( $web, $topic ) = @_;
207 my $viewUrl = TWiki::Func::getScriptUrl(
208 $web, $topic, 'viewauth' );
209 my $text = CGI::start_form(
210 -name => 'editpreferences',
212 -action => $viewUrl );
213 $text .= CGI::input({
215 name => 'prefsaction',
217 $text .= CGI::submit(-name => 'edit',
218 -value=>'Edit Preferences',
219 -class=>'twikiButton');
220 $text .= CGI::end_form();
225 # Generate the buttons that replace the EDITPREFERENCES tag in edit mode
226 sub _generateControlButtons {
227 my( $web, $topic ) = @_;
229 my $text = $START_MARKER.CGI::submit(-name=>'prefsaction',
230 -value=>'Save new settings',
231 -class=>'twikiSubmit',
234 $text .= CGI::submit(-name=>'prefsaction', -value=>'Cancel',
235 -class=>'twikiButton',
236 -accesskey=>'c').$END_MARKER;
240 # Given a Set in the topic being saved, look in the query to see
241 # if there is a new value for the Set and generate a new
244 my( $query, $web, $topic, $name, $value, $formDef ) = @_;
246 my $newValue = $query->param( $name ) || $value;
249 my $fieldDef = _getField( $formDef, $name );
250 my $type = $fieldDef->{type} || '';
251 if( $type && $type =~ /^checkbox/ ) {
253 my $vals = $fieldDef->{value};
254 foreach my $item ( @$vals ) {
255 my $cvalue = $query->param( $name.$item );
256 if( defined( $cvalue ) ) {
260 $val .= ', ' if( $cvalue );
262 $val .= $item if( $cvalue );
268 # if no form def, it's just treated as text
270 return $name.' = '.$newValue;