lib/TWiki/Plugins/PreferencesPlugin.pm
changeset 0 414e01d06fd5
child 1 e2915a7cbdfa
equal deleted inserted replaced
-1:000000000000 0:414e01d06fd5
       
     1 # Plugin for TWiki Enterprise Collaboration Platform, http://TWiki.org/
       
     2 #
       
     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.
       
     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 # For licensing info read LICENSE file in the TWiki root.
       
    19 
       
    20 # Still do to:
       
    21 # Handle continuation lines (see Prefs::parseText). These should always
       
    22 # go into a text area.
       
    23 
       
    24 package TWiki::Plugins::PreferencesPlugin;
       
    25 
       
    26 use strict;
       
    27 
       
    28 require TWiki::Func;    # The plugins API
       
    29 require TWiki::Plugins; # For the API version
       
    30 
       
    31 use vars qw( $VERSION $RELEASE @shelter );
       
    32 
       
    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) $';
       
    37 
       
    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';
       
    42 
       
    43 my $MARKER = "\007";
       
    44 
       
    45 # Markers used during form generation
       
    46 my $START_MARKER  = $MARKER.'STARTPREF'.$MARKER;
       
    47 my $END_MARKER    = $MARKER.'ENDPREF'.$MARKER;
       
    48 
       
    49 sub initPlugin {
       
    50     # check for Plugins.pm versions
       
    51     if( $TWiki::Plugins::VERSION < 1.026 ) {
       
    52         TWiki::Func::writeWarning( 'Version mismatch between PreferencesPlugin and Plugins.pm' );
       
    53         return 0;
       
    54     }
       
    55     @shelter = ();
       
    56 
       
    57     return 1;
       
    58 }
       
    59 
       
    60 sub beforeCommonTagsHandler {
       
    61     ### my ( $text, $topic, $web ) = @_;
       
    62     my $topic = $_[1];
       
    63     my $web = $_[2];
       
    64     return unless ( $_[0] =~ m/%EDITPREFERENCES(?:{(.*?)})?%/ );
       
    65 
       
    66     require CGI;
       
    67     require TWiki::Attrs;
       
    68     my $formDef;
       
    69     my $attrs = new TWiki::Attrs( $1 );
       
    70     if( defined( $attrs->{_DEFAULT} )) {
       
    71         my( $formWeb, $form ) = TWiki::Func::normalizeWebTopicName(
       
    72             $web, $attrs->{_DEFAULT} );
       
    73 
       
    74         # SMELL: Unpublished API. No choice, though :-(
       
    75         require TWiki::Form;    # SMELL
       
    76         $formDef =
       
    77           new TWiki::Form( $TWiki::Plugins::SESSION, $formWeb, $form );
       
    78     }
       
    79 
       
    80     my $query = TWiki::Func::getCgiQuery();
       
    81 
       
    82     my $action = lc $query->param( 'prefsaction' );
       
    83     $query->Delete( 'prefsaction' );
       
    84     $action =~ s/\s.*$//;
       
    85 
       
    86     if ( $action eq 'edit' ) {
       
    87         TWiki::Func::setTopicEditLock( $web, $topic, 1 );
       
    88         
       
    89         # Replace setting values by form fields but not inside comments Item4816
       
    90         my $outtext = '';
       
    91         my $insidecomment = 0;
       
    92         foreach my $token ( split/(<!--|-->)/, $_[0] ) {
       
    93             if ( $token =~ /<!--/ ) {
       
    94                 $insidecomment++;
       
    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;
       
   100             }
       
   101             $outtext .= $token;
       
   102         }
       
   103         $_[0] = $outtext;
       
   104           
       
   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',
       
   111             -method => 'post',
       
   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;
       
   118     }
       
   119 
       
   120     if( $action eq 'cancel' ) {
       
   121         TWiki::Func::setTopicEditLock( $web, $topic, 0 );
       
   122 
       
   123     } elsif( $action eq 'save' ) {
       
   124 
       
   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 );
       
   133         return;
       
   134     }
       
   135     # implicit action="view", or drop through from "save" or "cancel"
       
   136     $_[0] =~ s/%EDITPREFERENCES({.*?})?%/_generateEditButton($web, $topic)/ge;
       
   137 }
       
   138 
       
   139 # Use the post-rendering handler to plug our formatted editor units
       
   140 # into the text
       
   141 sub postRenderingHandler {
       
   142     ### my ( $text ) = @_;
       
   143 
       
   144     $_[0] =~ s/SHELTER$MARKER(\d+)/$shelter[$1]/g;
       
   145 }
       
   146 
       
   147 # Pluck the default value of a named field from a form definition
       
   148 sub _getField {
       
   149     my( $formDef, $name ) = @_;
       
   150     foreach my $f ( @{$formDef->{fields}} ) {
       
   151         if( $f->{name} eq $name ) {
       
   152             return $f;
       
   153         }
       
   154     }
       
   155     return undef;
       
   156 }
       
   157 
       
   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;
       
   164 
       
   165     my ($extras, $html);
       
   166 
       
   167     if( $formDef ) {
       
   168         my $fieldDef;
       
   169         if (defined(&TWiki::Form::getField)) {
       
   170             # TWiki 4.2 and later
       
   171             $fieldDef = $formDef->getField( $name );
       
   172         } else {
       
   173             # TWiki < 4.2
       
   174             $fieldDef = _getField( $formDef, $name );
       
   175         }
       
   176         if ( $fieldDef ) {
       
   177             if( defined(&TWiki::Form::renderFieldForEdit)) {
       
   178                 # TWiki < 4.2 SMELL: use of unpublished core function
       
   179                 ( $extras, $html ) =
       
   180                   $formDef->renderFieldForEdit( $fieldDef, $web, $topic, $value);
       
   181             } else {
       
   182                 # TWiki 4.2 and later SMELL: use of unpublished core function
       
   183                 ( $extras, $html ) =
       
   184                   $fieldDef->renderForEdit( $web, $topic, $value );
       
   185             }
       
   186         }
       
   187     }
       
   188     unless( $html ) {
       
   189         # No form definition, default to text field.
       
   190         $html = CGI::textfield( -class=>'twikiEditFormError twikiInputField',
       
   191                                 -name => $name,
       
   192                                 -size => 80, -value => $value );
       
   193     }
       
   194 
       
   195     push( @shelter, $html );
       
   196 
       
   197     return $START_MARKER.
       
   198       CGI::span({class=>'twikiAlert',
       
   199                  style=>'font-weight:bold;'},
       
   200                 $name . ' = SHELTER' . $MARKER . $#shelter).$END_MARKER;
       
   201 }
       
   202 
       
   203 # Generate the button that replaces the EDITPREFERENCES tag in view mode
       
   204 sub _generateEditButton {
       
   205     my( $web, $topic ) = @_;
       
   206 
       
   207     my $viewUrl = TWiki::Func::getScriptUrl(
       
   208         $web, $topic, 'viewauth' );
       
   209     my $text = CGI::start_form(
       
   210         -name => 'editpreferences',
       
   211         -method => 'post',
       
   212         -action => $viewUrl );
       
   213     $text .= CGI::input({
       
   214         type => 'hidden',
       
   215         name => 'prefsaction',
       
   216         value => 'edit'});
       
   217     $text .= CGI::submit(-name => 'edit',
       
   218                          -value=>'Edit Preferences',
       
   219                          -class=>'twikiButton');
       
   220     $text .= CGI::end_form();
       
   221     $text =~ s/\n//sg;
       
   222     return $text;
       
   223 }
       
   224 
       
   225 # Generate the buttons that replace the EDITPREFERENCES tag in edit mode
       
   226 sub _generateControlButtons {
       
   227     my( $web, $topic ) = @_;
       
   228 
       
   229     my $text = $START_MARKER.CGI::submit(-name=>'prefsaction',
       
   230                                          -value=>'Save new settings',
       
   231                                          -class=>'twikiSubmit',
       
   232                                          -accesskey=>'s');
       
   233     $text .= '&nbsp;';
       
   234     $text .= CGI::submit(-name=>'prefsaction', -value=>'Cancel',
       
   235                          -class=>'twikiButton',
       
   236                          -accesskey=>'c').$END_MARKER;
       
   237     return $text;
       
   238 }
       
   239 
       
   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
       
   242 # Set statement.
       
   243 sub _saveSet {
       
   244     my( $query, $web, $topic, $name, $value, $formDef ) = @_;
       
   245 
       
   246     my $newValue = $query->param( $name ) || $value;
       
   247 
       
   248     if( $formDef ) {
       
   249         my $fieldDef = _getField( $formDef, $name );
       
   250         my $type = $fieldDef->{type} || '';
       
   251         if( $type && $type =~ /^checkbox/ ) {
       
   252             my $val = '';
       
   253             my $vals = $fieldDef->{value};
       
   254             foreach my $item ( @$vals ) {
       
   255                 my $cvalue = $query->param( $name.$item );
       
   256                 if( defined( $cvalue ) ) {
       
   257                     if( ! $val ) {
       
   258                         $val = '';
       
   259                     } else {
       
   260                         $val .= ', ' if( $cvalue );
       
   261                     }
       
   262                     $val .= $item if( $cvalue );
       
   263                 }
       
   264             }
       
   265             $newValue = $val;
       
   266         }
       
   267     }
       
   268     # if no form def, it's just treated as text
       
   269 
       
   270     return $name.' = '.$newValue;
       
   271 }
       
   272 
       
   273 1;