Filename | /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugins/PreferencesPlugin.pm |
Statements | Executed 3419 statements in 18.4ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1131 | 1 | 1 | 14.6ms | 17.0ms | beforeCommonTagsHandler | Foswiki::Plugins::PreferencesPlugin::
1131 | 1 | 1 | 2.36ms | 2.36ms | CORE:match (opcode) | Foswiki::Plugins::PreferencesPlugin::
5 | 1 | 1 | 94µs | 141µs | postRenderingHandler | Foswiki::Plugins::PreferencesPlugin::
5 | 1 | 1 | 28µs | 28µs | CORE:subst (opcode) | Foswiki::Plugins::PreferencesPlugin::
1 | 1 | 1 | 25µs | 32µs | BEGIN@27 | Foswiki::Plugins::PreferencesPlugin::
5 | 1 | 1 | 19µs | 19µs | CORE:regcomp (opcode) | Foswiki::Plugins::PreferencesPlugin::
1 | 1 | 1 | 18µs | 18µs | initPlugin | Foswiki::Plugins::PreferencesPlugin::
1 | 1 | 1 | 16µs | 67µs | BEGIN@33 | Foswiki::Plugins::PreferencesPlugin::
1 | 1 | 1 | 16µs | 34µs | BEGIN@28 | Foswiki::Plugins::PreferencesPlugin::
1 | 1 | 1 | 10µs | 10µs | BEGIN@30 | Foswiki::Plugins::PreferencesPlugin::
1 | 1 | 1 | 9µs | 9µs | BEGIN@31 | Foswiki::Plugins::PreferencesPlugin::
0 | 0 | 0 | 0s | 0s | _generateControlButtons | Foswiki::Plugins::PreferencesPlugin::
0 | 0 | 0 | 0s | 0s | _generateEditButton | Foswiki::Plugins::PreferencesPlugin::
0 | 0 | 0 | 0s | 0s | _generateEditField | Foswiki::Plugins::PreferencesPlugin::
0 | 0 | 0 | 0s | 0s | _getField | Foswiki::Plugins::PreferencesPlugin::
0 | 0 | 0 | 0s | 0s | _saveSet | Foswiki::Plugins::PreferencesPlugin::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # See bottom of file for license and copyright information | ||||
2 | # Plugin for Foswiki - The Free and Open Source Wiki, http://foswiki.org/ | ||||
3 | # | ||||
4 | # Copyright (C) 2005-2009 Foswiki Contributors. | ||||
5 | # All Rights Reserved. Foswiki Contributors are listed in the | ||||
6 | # AUTHORS file in the root of this distribution. | ||||
7 | # NOTE: Please extend that file, not this notice. | ||||
8 | # | ||||
9 | # This program is free software; you can redistribute it and/or | ||||
10 | # modify it under the terms of the GNU General Public License | ||||
11 | # as published by the Free Software Foundation; either version 2 | ||||
12 | # of the License, or (at your option) any later version. For | ||||
13 | # more details read LICENSE in the root of this distribution. | ||||
14 | # | ||||
15 | # This program is distributed in the hope that it will be useful, | ||||
16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
18 | # | ||||
19 | # For licensing info read LICENSE file in the Foswiki root. | ||||
20 | |||||
21 | # Still do to: | ||||
22 | # Handle continuation lines (see Prefs::parseText). These should always | ||||
23 | # go into a text area. | ||||
24 | |||||
25 | package Foswiki::Plugins::PreferencesPlugin; | ||||
26 | |||||
27 | 2 | 46µs | 2 | 39µs | # spent 32µs (25+7) within Foswiki::Plugins::PreferencesPlugin::BEGIN@27 which was called:
# once (25µs+7µs) by Foswiki::Plugin::BEGIN@2.12 at line 27 # spent 32µs making 1 call to Foswiki::Plugins::PreferencesPlugin::BEGIN@27
# spent 7µs making 1 call to strict::import |
28 | 2 | 45µs | 2 | 52µs | # spent 34µs (16+18) within Foswiki::Plugins::PreferencesPlugin::BEGIN@28 which was called:
# once (16µs+18µs) by Foswiki::Plugin::BEGIN@2.12 at line 28 # spent 34µs making 1 call to Foswiki::Plugins::PreferencesPlugin::BEGIN@28
# spent 18µs making 1 call to warnings::import |
29 | |||||
30 | 2 | 38µs | 1 | 10µs | # spent 10µs within Foswiki::Plugins::PreferencesPlugin::BEGIN@30 which was called:
# once (10µs+0s) by Foswiki::Plugin::BEGIN@2.12 at line 30 # spent 10µs making 1 call to Foswiki::Plugins::PreferencesPlugin::BEGIN@30 |
31 | 2 | 55µs | 1 | 9µs | # spent 9µs within Foswiki::Plugins::PreferencesPlugin::BEGIN@31 which was called:
# once (9µs+0s) by Foswiki::Plugin::BEGIN@2.12 at line 31 # spent 9µs making 1 call to Foswiki::Plugins::PreferencesPlugin::BEGIN@31 |
32 | |||||
33 | 2 | 2.55ms | 2 | 117µs | # spent 67µs (16+50) within Foswiki::Plugins::PreferencesPlugin::BEGIN@33 which was called:
# once (16µs+50µs) by Foswiki::Plugin::BEGIN@2.12 at line 33 # spent 67µs making 1 call to Foswiki::Plugins::PreferencesPlugin::BEGIN@33
# spent 50µs making 1 call to vars::import |
34 | |||||
35 | 1 | 2µs | our $VERSION = '$Rev$'; | ||
36 | 1 | 1µs | our $RELEASE = '1.1.1'; | ||
37 | 1 | 1µs | our $SHORTDESCRIPTION = | ||
38 | 'Allows editing of preferences using fields predefined in a form'; | ||||
39 | 1 | 1µs | our $NO_PREFS_IN_TOPIC = 1; | ||
40 | |||||
41 | 1 | 2µs | my $MARKER = "\007"; | ||
42 | |||||
43 | # Markers used during form generation | ||||
44 | 1 | 2µs | my $START_MARKER = $MARKER . 'STARTPREF' . $MARKER; | ||
45 | 1 | 2µs | my $END_MARKER = $MARKER . 'ENDPREF' . $MARKER; | ||
46 | |||||
47 | # spent 18µs within Foswiki::Plugins::PreferencesPlugin::initPlugin which was called:
# once (18µs+0s) by Foswiki::Plugin::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugin.pm:235] at line 228 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugin.pm | ||||
48 | |||||
49 | # check for Plugins.pm versions | ||||
50 | 1 | 4µs | if ( $Foswiki::Plugins::VERSION < 1.026 ) { | ||
51 | Foswiki::Func::writeWarning( | ||||
52 | 'Version mismatch between PreferencesPlugin and Plugins.pm'); | ||||
53 | return 0; | ||||
54 | } | ||||
55 | 1 | 2µs | @shelter = (); | ||
56 | |||||
57 | 1 | 10µs | return 1; | ||
58 | } | ||||
59 | |||||
60 | # spent 17.0ms (14.6+2.36) within Foswiki::Plugins::PreferencesPlugin::beforeCommonTagsHandler which was called 1131 times, avg 15µs/call:
# 1131 times (14.6ms+2.36ms) by Foswiki::Plugin::invoke at line 287 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugin.pm, avg 15µs/call | ||||
61 | ### my ( $text, $topic, $web ) = @_; | ||||
62 | 1131 | 1.72ms | my $topic = $_[1]; | ||
63 | 1131 | 1.53ms | my $web = $_[2]; | ||
64 | 1131 | 12.2ms | 1131 | 2.36ms | return unless ( $_[0] =~ m/%EDITPREFERENCES(?:{(.*?)})?%/ ); # spent 2.36ms making 1131 calls to Foswiki::Plugins::PreferencesPlugin::CORE:match, avg 2µs/call |
65 | |||||
66 | require CGI; | ||||
67 | require Foswiki::Attrs; | ||||
68 | my $formDef; | ||||
69 | my $attrs = new Foswiki::Attrs($1); | ||||
70 | if ( defined( $attrs->{_DEFAULT} ) ) { | ||||
71 | my ( $formWeb, $form ) = | ||||
72 | Foswiki::Func::normalizeWebTopicName( $web, $attrs->{_DEFAULT} ); | ||||
73 | |||||
74 | # SMELL: Unpublished API. No choice, though :-( | ||||
75 | require Foswiki::Form; # SMELL | ||||
76 | $formDef = | ||||
77 | new Foswiki::Form( $Foswiki::Plugins::SESSION, $formWeb, $form ); | ||||
78 | } | ||||
79 | |||||
80 | my $query = Foswiki::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 | Foswiki::Func::setTopicEditLock( $web, $topic, 1 ); | ||||
88 | |||||
89 | # Replace setting values by form fields but not inside comments Item4816 | ||||
90 | # and also not inside verbatim blocks Item1117 | ||||
91 | my $outtext = ''; | ||||
92 | my $insidecomment = 0; | ||||
93 | my $insideverbatim = 0; | ||||
94 | foreach my $token ( split /(<!--|-->|<\/?verbatim\b[^>]*>)/, $_[0] ) { | ||||
95 | if ( !$insideverbatim and $token =~ /<!--/ ) { | ||||
96 | $insidecomment++; | ||||
97 | } | ||||
98 | elsif ( !$insideverbatim and $token =~ /-->/ ) { | ||||
99 | $insidecomment-- if ( $insidecomment > 0 ); | ||||
100 | } | ||||
101 | elsif ( $token =~ /<verbatim/ ) { | ||||
102 | $insideverbatim++; | ||||
103 | } | ||||
104 | elsif ( $token =~ /<\/verbatim/ ) { | ||||
105 | $insideverbatim-- if ( $insideverbatim > 0 ); | ||||
106 | } | ||||
107 | elsif ( !$insidecomment and !$insideverbatim ) { | ||||
108 | $token =~ | ||||
109 | s/^($Foswiki::regex{setRegex})($Foswiki::regex{tagNameRegex})\s*\=(.*$(?:\n[ \t]+[^\s*].*$)*)/ | ||||
110 | $1._generateEditField($web, $topic, $3, $4, $formDef)/gem; | ||||
111 | } | ||||
112 | $outtext .= $token; | ||||
113 | } | ||||
114 | $_[0] = $outtext; | ||||
115 | |||||
116 | $_[0] =~ s/%EDITPREFERENCES({.*?})?%/ | ||||
117 | _generateControlButtons($web, $topic)/ge; | ||||
118 | my $viewUrl = Foswiki::Func::getScriptUrl( $web, $topic, 'viewauth' ); | ||||
119 | my $startForm = CGI::start_form( | ||||
120 | -name => 'editpreferences', | ||||
121 | -method => 'post', | ||||
122 | -action => $viewUrl | ||||
123 | ); | ||||
124 | $startForm =~ s/\s+$//s; | ||||
125 | my $endForm = CGI::end_form(); | ||||
126 | $endForm =~ s/\s+$//s; | ||||
127 | $_[0] =~ | ||||
128 | s/^(.*?)$START_MARKER(.*)$END_MARKER(.*?)$/$1$startForm$2$endForm$3/s; | ||||
129 | $_[0] =~ s/$START_MARKER|$END_MARKER//gs; | ||||
130 | } | ||||
131 | |||||
132 | if ( $action eq 'cancel' ) { | ||||
133 | Foswiki::Func::setTopicEditLock( $web, $topic, 0 ); | ||||
134 | |||||
135 | } | ||||
136 | elsif ( $action eq 'save' ) { | ||||
137 | |||||
138 | # Make sure the request came from POST | ||||
139 | if ( $query && $query->method() && uc( $query->method() ) ne 'POST' ) { | ||||
140 | |||||
141 | # silently ignore it if the request didn't come from a POST | ||||
142 | } | ||||
143 | else { | ||||
144 | my ( $meta, $text ) = Foswiki::Func::readTopic( $web, $topic ); | ||||
145 | |||||
146 | # SMELL: unchecked implicit untaint of value? | ||||
147 | # $text =~ s/($Foswiki::regex{setVarRegex})/ | ||||
148 | $text =~ | ||||
149 | s/^($Foswiki::regex{setRegex})($Foswiki::regex{tagNameRegex})\s*\=(.*$(?:\n[ \t]+[^\s*].*$)*)/ | ||||
150 | $1._saveSet($query, $web, $topic, $3, $4, $formDef)/mgeo; | ||||
151 | Foswiki::Func::saveTopic( $web, $topic, $meta, $text ); | ||||
152 | } | ||||
153 | Foswiki::Func::setTopicEditLock( $web, $topic, 0 ); | ||||
154 | |||||
155 | # Finish with a redirect so that the *new* values are seen | ||||
156 | my $viewUrl = Foswiki::Func::getScriptUrl( $web, $topic, 'view' ); | ||||
157 | Foswiki::Func::redirectCgiQuery( undef, $viewUrl ); | ||||
158 | return; | ||||
159 | } | ||||
160 | |||||
161 | # implicit action="view", or drop through from "save" or "cancel" | ||||
162 | $_[0] =~ s/%EDITPREFERENCES({.*?})?%/_generateEditButton($web, $topic)/ge; | ||||
163 | } | ||||
164 | |||||
165 | # Use the post-rendering handler to plug our formatted editor units | ||||
166 | # into the text | ||||
167 | # spent 141µs (94+47) within Foswiki::Plugins::PreferencesPlugin::postRenderingHandler which was called 5 times, avg 28µs/call:
# 5 times (94µs+47µs) by Foswiki::Plugin::invoke at line 287 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Plugin.pm, avg 28µs/call | ||||
168 | ### my ( $text ) = @_; | ||||
169 | |||||
170 | 5 | 127µs | 10 | 47µs | $_[0] =~ s/SHELTER$MARKER(\d+)/$shelter[$1]/g; # spent 28µs making 5 calls to Foswiki::Plugins::PreferencesPlugin::CORE:subst, avg 6µs/call
# spent 19µs making 5 calls to Foswiki::Plugins::PreferencesPlugin::CORE:regcomp, avg 4µs/call |
171 | } | ||||
172 | |||||
173 | # Pluck the default value of a named field from a form definition | ||||
174 | sub _getField { | ||||
175 | my ( $formDef, $name ) = @_; | ||||
176 | foreach my $f ( @{ $formDef->{fields} } ) { | ||||
177 | if ( $f->{name} eq $name ) { | ||||
178 | return $f; | ||||
179 | } | ||||
180 | } | ||||
181 | return; | ||||
182 | } | ||||
183 | |||||
184 | # Generate a field suitable for editing this type. Use of the core | ||||
185 | # function 'renderFieldForEdit' ensures that we will pick up | ||||
186 | # extra edit types defined in other plugins. | ||||
187 | sub _generateEditField { | ||||
188 | my ( $web, $topic, $name, $value, $formDef ) = @_; | ||||
189 | $value =~ s/^\s*(.*?)\s*$/$1/ge; | ||||
190 | |||||
191 | my ( $extras, $html ); | ||||
192 | |||||
193 | if ($formDef) { | ||||
194 | my $fieldDef = $formDef->getField($name); | ||||
195 | if ($fieldDef) { | ||||
196 | my ($topicObject) = Foswiki::Func::readTopic( $web, $topic ); | ||||
197 | ( $extras, $html ) = | ||||
198 | $fieldDef->renderForEdit( $topicObject, $value ); | ||||
199 | } | ||||
200 | } | ||||
201 | unless ($html) { | ||||
202 | |||||
203 | if ( $value =~ /\n/ ) { | ||||
204 | my $rows = 1; | ||||
205 | $rows++ while $value =~ /\n/g; | ||||
206 | |||||
207 | # No form definition and there are newlines, default to textarea | ||||
208 | $html = CGI::textarea( | ||||
209 | -class => 'foswikiAlert foswikiInputField', | ||||
210 | -name => $name, | ||||
211 | -cols => 80, | ||||
212 | -rows => $rows, | ||||
213 | -default => $value | ||||
214 | ); | ||||
215 | } | ||||
216 | else { | ||||
217 | |||||
218 | # No form definition and no newlines, default to text field. | ||||
219 | $html = CGI::textfield( | ||||
220 | -class => 'foswikiAlert foswikiInputField', | ||||
221 | -name => $name, | ||||
222 | -size => 80, | ||||
223 | -value => $value | ||||
224 | ); | ||||
225 | } | ||||
226 | } | ||||
227 | |||||
228 | push( @shelter, $html ); | ||||
229 | |||||
230 | return $START_MARKER | ||||
231 | . CGI::span( | ||||
232 | { | ||||
233 | class => 'foswikiAlert', | ||||
234 | style => 'font-weight:bold;' | ||||
235 | }, | ||||
236 | $name . ' = SHELTER' . $MARKER . $#shelter | ||||
237 | ) . $END_MARKER; | ||||
238 | } | ||||
239 | |||||
240 | # Generate the button that replaces the EDITPREFERENCES tag in view mode | ||||
241 | sub _generateEditButton { | ||||
242 | my ( $web, $topic ) = @_; | ||||
243 | |||||
244 | my $viewUrl = Foswiki::Func::getScriptUrl( $web, $topic, 'viewauth' ); | ||||
245 | my $text = CGI::start_form( | ||||
246 | -name => 'editpreferences', | ||||
247 | -method => 'post', | ||||
248 | -action => $viewUrl | ||||
249 | ); | ||||
250 | $text .= CGI::input( | ||||
251 | { | ||||
252 | type => 'hidden', | ||||
253 | name => 'prefsaction', | ||||
254 | value => 'edit' | ||||
255 | } | ||||
256 | ); | ||||
257 | $text .= CGI::submit( | ||||
258 | -name => 'edit', | ||||
259 | -value => 'Edit Preferences', | ||||
260 | -class => 'foswikiButton' | ||||
261 | ); | ||||
262 | $text .= CGI::end_form(); | ||||
263 | $text =~ s/\n//sg; | ||||
264 | return $text; | ||||
265 | } | ||||
266 | |||||
267 | # Generate the buttons that replace the EDITPREFERENCES tag in edit mode | ||||
268 | sub _generateControlButtons { | ||||
269 | my ( $web, $topic ) = @_; | ||||
270 | |||||
271 | my $text = $START_MARKER | ||||
272 | . CGI::submit( | ||||
273 | -name => 'prefsaction', | ||||
274 | -value => 'Save new settings', | ||||
275 | -class => 'foswikiSubmit', | ||||
276 | -accesskey => 's' | ||||
277 | ); | ||||
278 | $text .= ' '; | ||||
279 | $text .= CGI::submit( | ||||
280 | -name => 'prefsaction', | ||||
281 | -value => 'Cancel', | ||||
282 | -class => 'foswikiButtonCancel', | ||||
283 | -accesskey => 'c' | ||||
284 | ) . $END_MARKER; | ||||
285 | return $text; | ||||
286 | } | ||||
287 | |||||
288 | # Given a Set in the topic being saved, look in the query to see | ||||
289 | # if there is a new value for the Set and generate a new | ||||
290 | # Set statement. | ||||
291 | sub _saveSet { | ||||
292 | my ( $query, $web, $topic, $name, $value, $formDef ) = @_; | ||||
293 | |||||
294 | my $newValue = $query->param($name); | ||||
295 | if ( not defined $newValue ) { | ||||
296 | $newValue = $value; | ||||
297 | $newValue =~ s/^\s+//; # strip leading whitespace | ||||
298 | } | ||||
299 | |||||
300 | if ($formDef) { | ||||
301 | my $fieldDef = _getField( $formDef, $name ); | ||||
302 | my $type = $fieldDef->{type} || ''; | ||||
303 | if ( $type && $type =~ /^checkbox/ ) { | ||||
304 | my $val = ''; | ||||
305 | my $vals = $fieldDef->{value}; | ||||
306 | foreach my $item (@$vals) { | ||||
307 | my $cvalue = $query->param( $name . $item ); | ||||
308 | if ( defined($cvalue) ) { | ||||
309 | if ( !$val ) { | ||||
310 | $val = ''; | ||||
311 | } | ||||
312 | else { | ||||
313 | $val .= ', ' if ($cvalue); | ||||
314 | } | ||||
315 | $val .= $item if ($cvalue); | ||||
316 | } | ||||
317 | } | ||||
318 | $newValue = $val; | ||||
319 | } | ||||
320 | } | ||||
321 | |||||
322 | # if no form def, it's just treated as text | ||||
323 | |||||
324 | return $name . ' = ' . $newValue; | ||||
325 | } | ||||
326 | |||||
327 | 1 | 9µs | 1; | ||
328 | __END__ | ||||
# spent 2.36ms within Foswiki::Plugins::PreferencesPlugin::CORE:match which was called 1131 times, avg 2µs/call:
# 1131 times (2.36ms+0s) by Foswiki::Plugins::PreferencesPlugin::beforeCommonTagsHandler at line 64, avg 2µs/call | |||||
# spent 19µs within Foswiki::Plugins::PreferencesPlugin::CORE:regcomp which was called 5 times, avg 4µs/call:
# 5 times (19µs+0s) by Foswiki::Plugins::PreferencesPlugin::postRenderingHandler at line 170, avg 4µs/call | |||||
# spent 28µs within Foswiki::Plugins::PreferencesPlugin::CORE:subst which was called 5 times, avg 6µs/call:
# 5 times (28µs+0s) by Foswiki::Plugins::PreferencesPlugin::postRenderingHandler at line 170, avg 6µs/call |