1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/lib/TWiki/Plugins/PreferencesPlugin.pm Sat Jan 26 15:50:53 2008 +0100
1.3 @@ -0,0 +1,273 @@
1.4 +# Plugin for TWiki Enterprise Collaboration Platform, http://TWiki.org/
1.5 +#
1.6 +# Copyright (C) 2005-2007 TWiki Contributors.
1.7 +# All Rights Reserved. TWiki Contributors are listed in the
1.8 +# AUTHORS file in the root of this distribution.
1.9 +# NOTE: Please extend that file, not this notice.
1.10 +#
1.11 +# This program is free software; you can redistribute it and/or
1.12 +# modify it under the terms of the GNU General Public License
1.13 +# as published by the Free Software Foundation; either version 2
1.14 +# of the License, or (at your option) any later version. For
1.15 +# more details read LICENSE in the root of this distribution.
1.16 +#
1.17 +# This program is distributed in the hope that it will be useful,
1.18 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
1.19 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1.20 +#
1.21 +# For licensing info read LICENSE file in the TWiki root.
1.22 +
1.23 +# Still do to:
1.24 +# Handle continuation lines (see Prefs::parseText). These should always
1.25 +# go into a text area.
1.26 +
1.27 +package TWiki::Plugins::PreferencesPlugin;
1.28 +
1.29 +use strict;
1.30 +
1.31 +require TWiki::Func; # The plugins API
1.32 +require TWiki::Plugins; # For the API version
1.33 +
1.34 +use vars qw( $VERSION $RELEASE @shelter );
1.35 +
1.36 +# This should always be $Rev: 15487 (22 Jan 2008) $ so that TWiki can determine the checked-in
1.37 +# status of the plugin. It is used by the build automation tools, so
1.38 +# you should leave it alone.
1.39 +$VERSION = '$Rev: 15487 (22 Jan 2008) $';
1.40 +
1.41 +# This is a free-form string you can use to "name" your own plugin version.
1.42 +# It is *not* used by the build automation tools, but is reported as part
1.43 +# of the version number in PLUGINDESCRIPTIONS.
1.44 +$RELEASE = 'TWiki-4.2';
1.45 +
1.46 +my $MARKER = "\007";
1.47 +
1.48 +# Markers used during form generation
1.49 +my $START_MARKER = $MARKER.'STARTPREF'.$MARKER;
1.50 +my $END_MARKER = $MARKER.'ENDPREF'.$MARKER;
1.51 +
1.52 +sub initPlugin {
1.53 + # check for Plugins.pm versions
1.54 + if( $TWiki::Plugins::VERSION < 1.026 ) {
1.55 + TWiki::Func::writeWarning( 'Version mismatch between PreferencesPlugin and Plugins.pm' );
1.56 + return 0;
1.57 + }
1.58 + @shelter = ();
1.59 +
1.60 + return 1;
1.61 +}
1.62 +
1.63 +sub beforeCommonTagsHandler {
1.64 + ### my ( $text, $topic, $web ) = @_;
1.65 + my $topic = $_[1];
1.66 + my $web = $_[2];
1.67 + return unless ( $_[0] =~ m/%EDITPREFERENCES(?:{(.*?)})?%/ );
1.68 +
1.69 + require CGI;
1.70 + require TWiki::Attrs;
1.71 + my $formDef;
1.72 + my $attrs = new TWiki::Attrs( $1 );
1.73 + if( defined( $attrs->{_DEFAULT} )) {
1.74 + my( $formWeb, $form ) = TWiki::Func::normalizeWebTopicName(
1.75 + $web, $attrs->{_DEFAULT} );
1.76 +
1.77 + # SMELL: Unpublished API. No choice, though :-(
1.78 + require TWiki::Form; # SMELL
1.79 + $formDef =
1.80 + new TWiki::Form( $TWiki::Plugins::SESSION, $formWeb, $form );
1.81 + }
1.82 +
1.83 + my $query = TWiki::Func::getCgiQuery();
1.84 +
1.85 + my $action = lc $query->param( 'prefsaction' );
1.86 + $query->Delete( 'prefsaction' );
1.87 + $action =~ s/\s.*$//;
1.88 +
1.89 + if ( $action eq 'edit' ) {
1.90 + TWiki::Func::setTopicEditLock( $web, $topic, 1 );
1.91 +
1.92 + # Replace setting values by form fields but not inside comments Item4816
1.93 + my $outtext = '';
1.94 + my $insidecomment = 0;
1.95 + foreach my $token ( split/(<!--|-->)/, $_[0] ) {
1.96 + if ( $token =~ /<!--/ ) {
1.97 + $insidecomment++;
1.98 + } elsif ( $token =~ /-->/ ) {
1.99 + $insidecomment-- if ( $insidecomment > 0 );
1.100 + } elsif ( !$insidecomment ) {
1.101 + $token =~ s(^((?:\t| )+\*\sSet\s*)(\w+)\s*\=(.*$(\n[ \t]+[^\s*].*$)*))
1.102 + ($1._generateEditField($web, $topic, $2, $3, $formDef))gem;
1.103 + }
1.104 + $outtext .= $token;
1.105 + }
1.106 + $_[0] = $outtext;
1.107 +
1.108 + $_[0] =~ s/%EDITPREFERENCES({.*?})?%/
1.109 + _generateControlButtons($web, $topic)/ge;
1.110 + my $viewUrl = TWiki::Func::getScriptUrl(
1.111 + $web, $topic, 'viewauth' );
1.112 + my $startForm = CGI::start_form(
1.113 + -name => 'editpreferences',
1.114 + -method => 'post',
1.115 + -action => $viewUrl );
1.116 + $startForm =~ s/\s+$//s;
1.117 + my $endForm = CGI::end_form();
1.118 + $endForm =~ s/\s+$//s;
1.119 + $_[0] =~ s/^(.*?)$START_MARKER(.*)$END_MARKER(.*?)$/$1$startForm$2$endForm$3/s;
1.120 + $_[0] =~ s/$START_MARKER|$END_MARKER//gs;
1.121 + }
1.122 +
1.123 + if( $action eq 'cancel' ) {
1.124 + TWiki::Func::setTopicEditLock( $web, $topic, 0 );
1.125 +
1.126 + } elsif( $action eq 'save' ) {
1.127 +
1.128 + my( $meta, $text ) = TWiki::Func::readTopic( $web, $topic );
1.129 + $text =~ s(^((?:\t| )+\*\sSet\s)(\w+)\s\=\s(.*)$)
1.130 + ($1._saveSet($query, $web, $topic, $2, $3, $formDef))mgeo;
1.131 + TWiki::Func::saveTopic( $web, $topic, $meta, $text );
1.132 + TWiki::Func::setTopicEditLock( $web, $topic, 0 );
1.133 + # Finish with a redirect so that the *new* values are seen
1.134 + my $viewUrl = TWiki::Func::getScriptUrl( $web, $topic, 'view' );
1.135 + TWiki::Func::redirectCgiQuery( undef, $viewUrl );
1.136 + return;
1.137 + }
1.138 + # implicit action="view", or drop through from "save" or "cancel"
1.139 + $_[0] =~ s/%EDITPREFERENCES({.*?})?%/_generateEditButton($web, $topic)/ge;
1.140 +}
1.141 +
1.142 +# Use the post-rendering handler to plug our formatted editor units
1.143 +# into the text
1.144 +sub postRenderingHandler {
1.145 + ### my ( $text ) = @_;
1.146 +
1.147 + $_[0] =~ s/SHELTER$MARKER(\d+)/$shelter[$1]/g;
1.148 +}
1.149 +
1.150 +# Pluck the default value of a named field from a form definition
1.151 +sub _getField {
1.152 + my( $formDef, $name ) = @_;
1.153 + foreach my $f ( @{$formDef->{fields}} ) {
1.154 + if( $f->{name} eq $name ) {
1.155 + return $f;
1.156 + }
1.157 + }
1.158 + return undef;
1.159 +}
1.160 +
1.161 +# Generate a field suitable for editing this type. Use of the core
1.162 +# function 'renderFieldForEdit' ensures that we will pick up
1.163 +# extra edit types defined in other plugins.
1.164 +sub _generateEditField {
1.165 + my( $web, $topic, $name, $value, $formDef ) = @_;
1.166 + $value =~ s/^\s*(.*?)\s*$/$1/ge;
1.167 +
1.168 + my ($extras, $html);
1.169 +
1.170 + if( $formDef ) {
1.171 + my $fieldDef;
1.172 + if (defined(&TWiki::Form::getField)) {
1.173 + # TWiki 4.2 and later
1.174 + $fieldDef = $formDef->getField( $name );
1.175 + } else {
1.176 + # TWiki < 4.2
1.177 + $fieldDef = _getField( $formDef, $name );
1.178 + }
1.179 + if ( $fieldDef ) {
1.180 + if( defined(&TWiki::Form::renderFieldForEdit)) {
1.181 + # TWiki < 4.2 SMELL: use of unpublished core function
1.182 + ( $extras, $html ) =
1.183 + $formDef->renderFieldForEdit( $fieldDef, $web, $topic, $value);
1.184 + } else {
1.185 + # TWiki 4.2 and later SMELL: use of unpublished core function
1.186 + ( $extras, $html ) =
1.187 + $fieldDef->renderForEdit( $web, $topic, $value );
1.188 + }
1.189 + }
1.190 + }
1.191 + unless( $html ) {
1.192 + # No form definition, default to text field.
1.193 + $html = CGI::textfield( -class=>'twikiEditFormError twikiInputField',
1.194 + -name => $name,
1.195 + -size => 80, -value => $value );
1.196 + }
1.197 +
1.198 + push( @shelter, $html );
1.199 +
1.200 + return $START_MARKER.
1.201 + CGI::span({class=>'twikiAlert',
1.202 + style=>'font-weight:bold;'},
1.203 + $name . ' = SHELTER' . $MARKER . $#shelter).$END_MARKER;
1.204 +}
1.205 +
1.206 +# Generate the button that replaces the EDITPREFERENCES tag in view mode
1.207 +sub _generateEditButton {
1.208 + my( $web, $topic ) = @_;
1.209 +
1.210 + my $viewUrl = TWiki::Func::getScriptUrl(
1.211 + $web, $topic, 'viewauth' );
1.212 + my $text = CGI::start_form(
1.213 + -name => 'editpreferences',
1.214 + -method => 'post',
1.215 + -action => $viewUrl );
1.216 + $text .= CGI::input({
1.217 + type => 'hidden',
1.218 + name => 'prefsaction',
1.219 + value => 'edit'});
1.220 + $text .= CGI::submit(-name => 'edit',
1.221 + -value=>'Edit Preferences',
1.222 + -class=>'twikiButton');
1.223 + $text .= CGI::end_form();
1.224 + $text =~ s/\n//sg;
1.225 + return $text;
1.226 +}
1.227 +
1.228 +# Generate the buttons that replace the EDITPREFERENCES tag in edit mode
1.229 +sub _generateControlButtons {
1.230 + my( $web, $topic ) = @_;
1.231 +
1.232 + my $text = $START_MARKER.CGI::submit(-name=>'prefsaction',
1.233 + -value=>'Save new settings',
1.234 + -class=>'twikiSubmit',
1.235 + -accesskey=>'s');
1.236 + $text .= ' ';
1.237 + $text .= CGI::submit(-name=>'prefsaction', -value=>'Cancel',
1.238 + -class=>'twikiButton',
1.239 + -accesskey=>'c').$END_MARKER;
1.240 + return $text;
1.241 +}
1.242 +
1.243 +# Given a Set in the topic being saved, look in the query to see
1.244 +# if there is a new value for the Set and generate a new
1.245 +# Set statement.
1.246 +sub _saveSet {
1.247 + my( $query, $web, $topic, $name, $value, $formDef ) = @_;
1.248 +
1.249 + my $newValue = $query->param( $name ) || $value;
1.250 +
1.251 + if( $formDef ) {
1.252 + my $fieldDef = _getField( $formDef, $name );
1.253 + my $type = $fieldDef->{type} || '';
1.254 + if( $type && $type =~ /^checkbox/ ) {
1.255 + my $val = '';
1.256 + my $vals = $fieldDef->{value};
1.257 + foreach my $item ( @$vals ) {
1.258 + my $cvalue = $query->param( $name.$item );
1.259 + if( defined( $cvalue ) ) {
1.260 + if( ! $val ) {
1.261 + $val = '';
1.262 + } else {
1.263 + $val .= ', ' if( $cvalue );
1.264 + }
1.265 + $val .= $item if( $cvalue );
1.266 + }
1.267 + }
1.268 + $newValue = $val;
1.269 + }
1.270 + }
1.271 + # if no form def, it's just treated as text
1.272 +
1.273 + return $name.' = '.$newValue;
1.274 +}
1.275 +
1.276 +1;