Filename | /var/www/foswiki11/lib/Foswiki/Plugins/ChecklistPlugin.pm |
Statements | Executed 323 statements in 8.38ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
13 | 1 | 1 | 638µs | 937µs | commonTagsHandler | Foswiki::Plugins::ChecklistPlugin::
13 | 1 | 1 | 299µs | 299µs | handleAllTags | Foswiki::Plugins::ChecklistPlugin::
5 | 1 | 1 | 137µs | 433µs | postRenderingHandler | Foswiki::Plugins::ChecklistPlugin::
1 | 1 | 1 | 67µs | 71µs | initDefaults | Foswiki::Plugins::ChecklistPlugin::
1 | 1 | 1 | 37µs | 249µs | initPlugin | Foswiki::Plugins::ChecklistPlugin::
1 | 1 | 1 | 18µs | 214µs | BEGIN@23 | Foswiki::Plugins::ChecklistPlugin::
1 | 1 | 1 | 9µs | 22µs | BEGIN@35 | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | checkChangeAccessPermission | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | collectAllChecklistItems | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | createAction | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | createHiddenDirectResetSelectionDiv | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | createHiddenDirectSelectionDiv | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | createResetAction | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | createTitle | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | createUnknownParamsMessage | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | doChecklistItemStateChange | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | doChecklistItemStateReset | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | endRenderingHandler | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | extractPerms | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | getClisTopicName | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | getImageSrc | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | getLogEntry | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | getName | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | getNextState | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | getUniqueUrlParam | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | handleAutoChecklist | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | handleChecklist | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | handleChecklistItem | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | handleDescription | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | handleStateChanges | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | htmlEncode | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | initNamedDefaults | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | initOptions | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | initStates | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | readChecklistItemStateTopic | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | renderChecklistItem | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | renderLegend | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | saveChecklistItemStateTopic | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | saveLog | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | substAttributes | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | substIllegalChars | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | substItemLine | Foswiki::Plugins::ChecklistPlugin::
0 | 0 | 0 | 0s | 0s | urlEncode | Foswiki::Plugins::ChecklistPlugin::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # Plugin for Foswiki - The Free and Open Source Wiki, http://foswiki.org/ | ||||
2 | # | ||||
3 | # Copyright (C) 2000-2003 Andrea Sterbini, a.sterbini@flashnet.it | ||||
4 | # Copyright (C) 2001-2004 Peter Thoeny, peter@thoeny.com | ||||
5 | # Copyright (C) 2005-2009 Daniel Rohde | ||||
6 | # | ||||
7 | # This program is free software; you can redistribute it and/or | ||||
8 | # modify it under the terms of the GNU General Public License | ||||
9 | # as published by the Free Software Foundation; either version 2 | ||||
10 | # of the License, or (at your option) any later version. | ||||
11 | # | ||||
12 | # This program is distributed in the hope that it will be useful, | ||||
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
15 | # GNU General Public License for more details, published at | ||||
16 | # http://www.gnu.org/copyleft/gpl.html | ||||
17 | # | ||||
18 | |||||
19 | # ========================= | ||||
20 | package Foswiki::Plugins::ChecklistPlugin; | ||||
21 | |||||
22 | # ========================= | ||||
23 | 1 | 7µs | 1 | 196µs | # spent 214µs (18+196) within Foswiki::Plugins::ChecklistPlugin::BEGIN@23 which was called:
# once (18µs+196µs) by Foswiki::Plugin::BEGIN@2.7 at line 33 # spent 196µs making 1 call to vars::import |
24 | $installWeb $VERSION $RELEASE $REVISION $pluginName | ||||
25 | $debug %FoswikiCompatibility | ||||
26 | %globalDefaults @renderedOptions @flagOptions @filteredOptions @listOptions @ignoreNamedDefaults | ||||
27 | %options @unknownParams | ||||
28 | %namedDefaults %namedIds $idMapRef $idOrderRef %namedResetIds %itemStatesRead | ||||
29 | $resetDone $stateChangeDone $saveDone | ||||
30 | $initText %itemsCollected $dryrun | ||||
31 | $web $topic $user | ||||
32 | $idOffset | ||||
33 | 1 | 28µs | 1 | 214µs | ); # spent 214µs making 1 call to Foswiki::Plugins::ChecklistPlugin::BEGIN@23 |
34 | |||||
35 | 2 | 7.22ms | 2 | 34µs | # spent 22µs (9+12) within Foswiki::Plugins::ChecklistPlugin::BEGIN@35 which was called:
# once (9µs+12µs) by Foswiki::Plugin::BEGIN@2.7 at line 35 # spent 22µs making 1 call to Foswiki::Plugins::ChecklistPlugin::BEGIN@35
# spent 12µs making 1 call to strict::import |
36 | ####use warnings; | ||||
37 | |||||
38 | 1 | 1µs | $FoswikiCompatibility{endRenderingHandler} = 1.1; | ||
39 | |||||
40 | 1 | 400ns | $VERSION = '$Rev: 5335 (2009-10-21) $'; | ||
41 | |||||
42 | 1 | 400ns | $RELEASE = 'Cairo, Dakar, Edinburgh, ...'; | ||
43 | |||||
44 | |||||
45 | 1 | 200ns | $REVISION = '1.026'; #dro# added timestamp feature requested by TWiki:Main.VickiBrown; fixed uninitialized value bugs; | ||
46 | #$REVISION = '1.025'; #dro# added documentation requested by TWiki:Main.PeterThoeny; added hide entries feature requested by Christian Holzmann; added log feature requested by TWiki:Main.VickiBrown | ||||
47 | #$REVISION = '1.024'; #dro# fixed missing ')' in generated JavaScript commands | ||||
48 | #$REVISION = '1.023'; #dro# fixed minor anchor link bug reported by TWiki:Main.KeithHelfrich; fixed tooltip position bug | ||||
49 | #$REVISION = '1.022'; #dro# improved AJAX performance; added new feature (state selection for reset button); fixed %TOC% bug reported by TWiki:Main.HelenJohnstone; fixed some minor and major bugs (mod_perl, description stripping, static feature, 'text' icons); removed useforms feature | ||||
50 | #$REVISION = '1.021'; #dro# fixed some major bug (mod_perl, plugin preferences); improved performance (AJAX); fixed minor IE caching bug (AJAX related); added new attributes (tooltip, descr, template, statesel) requested by TWiki:Main.KeithHelfrich; fixed installation instructions bug reported by TWiki:Main.KeithHelfrich | ||||
51 | #$REVISION = '1.020'; #dro# added AJAX feature (useajax attribute) requested by TWiki:Main.ShayPierce and TWiki:Main.KeithHelfrich | ||||
52 | #$REVISION = '1.019'; #dro# fixed major default options bug reported by TWiki:Main.RichardHitier | ||||
53 | #$REVISION = '1.018'; #dro# fixed notification bug reported by TWiki:Main.JosMaccabiani; fixed a minor whitespace bug; add static attribute | ||||
54 | #$REVISION = '1.017'; #dro# fixed access right bug; disabled change/create mail notification (added attribute: notify) | ||||
55 | #$REVISION = '1.016'; #dro# fixed access right bug reported by TWiki:Main.SaschaVogt | ||||
56 | #$REVISION = '1.015'; #dro# fixed mod_perl preload bug (removed 'use warnings;') reported by Foswiki:Main.KennethLavrsen | ||||
57 | #$REVISION = '1.014'; #dro# fixed mod_perl bug; fixed deprecated handler problem | ||||
58 | #$REVISION = '1.013'; #dro# fixed anchor bug; fixed multiple save bug (performance improvement); fixed reset bugs in named checklists | ||||
59 | #$REVISION = '1.012'; #dro# fixed a minor statetopic bug; improved autogenerated checklists (item insertion without state lost); improved docs | ||||
60 | #$REVISION = '1.011'; #dro# fixed documentation; fixed reset bug (that comes with URL parameter bug fix); added statetopic attribute | ||||
61 | #$REVISION = '1.010'; #dro# fixed URL parameter bugs (preserve URL parameters; URL encoding); used CGI module to generate HTML; fixed table sorting bug in a ChecklistItemState topic | ||||
62 | #$REVISION = '1.009'; #dro# fixed stateicons handling; fixed TablePlugin sorting problem | ||||
63 | #$REVISION = '1.008'; #dro# fixed docs; changed default text positioning (text attribute); allowed common variable usage in stateicons attribute; fixed multiple checklists bugs | ||||
64 | #$REVISION = '1.007'; #dro# added new feature (CHECKLISTSTART/END tags, attributes: clipos, pos); fixed bugs | ||||
65 | #$REVISION = '1.006'; #dro# added new attribute (useforms); fixed legend bug; fixed HTML encoding bug | ||||
66 | #$REVISION = '1.005'; #dro# fixed major bug (edit lock); fixed html encoding; improved doc | ||||
67 | #$REVISION = '1.004'; #dro# added unknown parameter handling (new attribute: unknownparamsmsg); added 'set to a given state' feature; changed reset behavior; fixed typos | ||||
68 | #$VERSION = '1.003'; #dro# added attributes (showlegend, anchors); fixed states bug (illegal characters in states option); improved documentation; fixed typos; fixed some minor bugs | ||||
69 | #$VERSION = '1.002'; #dro# fixed cache problems; fixed HTML/URL encoding bugs; fixed reload bug; fixed reset image button bug; added anchors | ||||
70 | #$VERSION = '1.001'; #dro# added new features ('reset','text' attributes); fixed 'name' attribute bug; fixed documentation bugs | ||||
71 | #$VERSION = '1.000'; #dro# initial version | ||||
72 | |||||
73 | 1 | 200ns | $pluginName = 'ChecklistPlugin'; # Name of this Plugin | ||
74 | |||||
75 | # ========================= | ||||
76 | sub initPlugin | ||||
77 | # spent 249µs (37+211) within Foswiki::Plugins::ChecklistPlugin::initPlugin which was called:
# once (37µs+211µs) by Foswiki::Plugin::__ANON__[/var/www/foswiki11/lib/Foswiki/Plugin.pm:241] at line 234 of /var/www/foswiki11/lib/Foswiki/Plugin.pm | ||||
78 | 1 | 3µs | ( $topic, $web, $user, $installWeb ) = @_; | ||
79 | |||||
80 | # check for Plugins.pm versions | ||||
81 | 1 | 21µs | 1 | 13µs | if( $Foswiki::Plugins::VERSION < 1.021 ) { # spent 13µs making 1 call to version::vxs::VCMP |
82 | Foswiki::Func::writeWarning( "Version mismatch between $pluginName and Plugins.pm" ); | ||||
83 | return 0; | ||||
84 | } | ||||
85 | |||||
86 | # Get plugin debug flag | ||||
87 | 1 | 4µs | 1 | 127µs | $debug = Foswiki::Func::getPluginPreferencesFlag( "DEBUG" ); # spent 127µs making 1 call to Foswiki::Func::getPluginPreferencesFlag |
88 | |||||
89 | # XXX | ||||
90 | ####$debug = 1; | ||||
91 | |||||
92 | 1 | 6µs | 1 | 71µs | &initDefaults($web, $topic); # spent 71µs making 1 call to Foswiki::Plugins::ChecklistPlugin::initDefaults |
93 | |||||
94 | # Plugin correctly initialized | ||||
95 | 1 | 300ns | Foswiki::Func::writeDebug( "- Foswiki::Plugins::${pluginName}::initPlugin( $web.$topic ) is OK" ) if $debug; | ||
96 | 1 | 6µs | return 1; | ||
97 | } | ||||
98 | |||||
99 | # ========================= | ||||
100 | sub commonTagsHandler | ||||
101 | # spent 937µs (638+299) within Foswiki::Plugins::ChecklistPlugin::commonTagsHandler which was called 13 times, avg 72µs/call:
# 13 times (638µs+299µs) by Foswiki::Plugin::invoke at line 294 of /var/www/foswiki11/lib/Foswiki/Plugin.pm, avg 72µs/call | ||||
102 | ### my ( $text, $topic, $web ) = @_; # do not uncomment, use $_[0], $_[1]... instead | ||||
103 | |||||
104 | 13 | 5µs | Foswiki::Func::writeDebug( "- ${pluginName}::commonTagsHandler( $_[2].$_[1] )" ) if $debug; | ||
105 | |||||
106 | # This is the place to define customized tags and variables | ||||
107 | # Called by Foswiki::handleCommonTags, after %INCLUDE:"..."% | ||||
108 | |||||
109 | 13 | 60µs | local(%namedDefaults, %itemStatesRead, %namedIds, %namedResetIds, @unknownParams, $initText, $resetDone,$stateChangeDone,$saveDone,$idMapRef,$idOrderRef, %itemsCollected, $dryrun); | ||
110 | |||||
111 | 13 | 69µs | $initText = $_[0] if $_[0] =~ /\%(CLI|CHECKLIST)/; | ||
112 | |||||
113 | 13 | 8µs | $idMapRef = { }; | ||
114 | 13 | 7µs | $idOrderRef = { }; | ||
115 | 13 | 11µs | %namedIds = ( ); | ||
116 | 13 | 3µs | %namedResetIds = ( ); | ||
117 | |||||
118 | 13 | 4µs | $resetDone = 0; | ||
119 | 13 | 2µs | $stateChangeDone = 0; | ||
120 | 13 | 2µs | $saveDone = 0; | ||
121 | |||||
122 | 13 | 2µs | $dryrun = 0; | ||
123 | |||||
124 | 13 | 6µs | %namedDefaults = ( ); | ||
125 | 13 | 3µs | %itemStatesRead = ( ); | ||
126 | 13 | 6µs | %itemsCollected = ( ); | ||
127 | |||||
128 | |||||
129 | 13 | 314µs | $_[0] =~ s/<\/head>/<script src="%PUBURL%\/%SYSTEMWEB%\/$pluginName\/itemstatechange.js" language="javascript" type="text\/javascript"><\/script><\/head>/is unless ($_[0]=~/itemstatechange.js/); | ||
130 | 13 | 83µs | 13 | 299µs | &handleAllTags(@_); # spent 299µs making 13 calls to Foswiki::Plugins::ChecklistPlugin::handleAllTags, avg 23µs/call |
131 | } | ||||
132 | |||||
133 | # ========================= | ||||
134 | # spent 299µs within Foswiki::Plugins::ChecklistPlugin::handleAllTags which was called 13 times, avg 23µs/call:
# 13 times (299µs+0s) by Foswiki::Plugins::ChecklistPlugin::commonTagsHandler at line 130, avg 23µs/call | ||||
135 | |||||
136 | ### my ( $text, $topic, $web ) = @_; # do not uncomment, use $_[0], $_[1]... instead | ||||
137 | # | ||||
138 | |||||
139 | |||||
140 | 13 | 35µs | $_[0] =~ s/%CHECKLISTSTART%(.*?)%CHECKLISTEND%/&handleAutoChecklist("",$1,$_[0])/sge; | ||
141 | 13 | 36µs | $_[0] =~ s/%CHECKLISTSTART{(.*?)}%(.*?)%CHECKLISTEND%/&handleAutoChecklist($1,$2,$_[0])/sge; | ||
142 | 13 | 43µs | $_[0] =~ s/%CHECKLIST%/&handleChecklist("",$_[0])/ge; | ||
143 | 13 | 42µs | $_[0] =~ s/%CHECKLIST{(.*?)}%/&handleChecklist($1,$_[0])/sge; | ||
144 | 13 | 173µs | $_[0] =~ s/%CLI({(.*?)})?%/&handleChecklistItem($2,$_[0],$-[0],$+[0])/sge; | ||
145 | |||||
146 | ##$_[0] =~ s/([^\n\%]*)%CLI({(.*?)})?%([^\n\%]*)/$1.&handleChecklistItem($3,$_[0],$1,$4).$4/sge; | ||||
147 | } | ||||
148 | |||||
149 | # ========================= | ||||
150 | # spent 71µs (67+4) within Foswiki::Plugins::ChecklistPlugin::initDefaults which was called:
# once (67µs+4µs) by Foswiki::Plugins::ChecklistPlugin::initPlugin at line 92 | ||||
151 | 1 | 2µs | my ($web, $topic) = @_; | ||
152 | 1 | 500ns | Foswiki::Func::writeDebug("- ${pluginName}::initDefaults") if $debug; | ||
153 | |||||
154 | 1 | 4µs | 1 | 4µs | my $pubUrlPath = Foswiki::Func::getPubUrlPath(); # spent 4µs making 1 call to Foswiki::Func::getPubUrlPath |
155 | 1 | 45µs | %globalDefaults = ( | ||
156 | 'id' => undef, | ||||
157 | 'name' => '_default', | ||||
158 | 'states' => 'todo|done', | ||||
159 | 'stateicons' =>':-I|:ok:', | ||||
160 | 'text' => '', | ||||
161 | 'reset' => undef, | ||||
162 | 'showlegend' => 0, | ||||
163 | 'anchors' => 1, | ||||
164 | 'unknownparamsmsg' => '%RED% Sorry, some parameters are unknown: %UNKNOWNPARAMSLIST% %ENDCOLOR% <br/> Allowed parameters are (see %SYSTEMWEB%.ChecklistPlugin topic for more details): %KNOWNPARAMSLIST%', | ||||
165 | 'clipos'=> 'right', | ||||
166 | 'pos'=>'bottom', | ||||
167 | 'statetopic'=> $topic.'ChecklistItemState', | ||||
168 | 'notify'=> 0, | ||||
169 | 'static'=> 0, | ||||
170 | 'useajax'=>1, | ||||
171 | 'tooltip'=>'Click me to change my state from \'%STATE%\' to \'%NEXTSTATE%\' <br/>t: %TIMESTAMP%', | ||||
172 | 'tooltipbgcolor'=>'%WEBBGCOLOR%', | ||||
173 | 'descr' => undef, | ||||
174 | '_DEFAULT' => undef, | ||||
175 | 'ajaxtopicstyle'=>'plain', | ||||
176 | 'descrcharlimit'=>100, | ||||
177 | 'template' => undef, | ||||
178 | 'statesel' => 0, | ||||
179 | 'tooltipfixleft' => '-163', | ||||
180 | 'tooltipfixtop' => '0', | ||||
181 | 'hide'=> undef, | ||||
182 | 'log'=> 0, | ||||
183 | 'logformat'=>" * %SERVERTIME% - %WIKIUSERNAME% - Item %CLIID%: from %STATE% to %NEXTSTATE% \n", | ||||
184 | 'logtopic'=>$topic.'ChecklistLog', | ||||
185 | 'logpos' => 'append', | ||||
186 | 'timestampformat' => '%SERVERTIME% - %WIKIUSERNAME%, last state: %STATE%', | ||||
187 | ); | ||||
188 | |||||
189 | 1 | 2µs | @listOptions = ('states','stateicons'); | ||
190 | 1 | 2µs | @renderedOptions = ( 'text', 'stateicons', 'reset', 'hide' ); | ||
191 | |||||
192 | 1 | 1µs | @filteredOptions = ( 'id', 'name', 'states'); | ||
193 | |||||
194 | 1 | 2µs | @flagOptions = ('showlegend', 'anchors', 'notify', 'static' , 'useajax', 'statesel', 'log'); | ||
195 | |||||
196 | 1 | 8µs | @ignoreNamedDefaults = ('showlegend','reset','hide'); | ||
197 | } | ||||
198 | |||||
199 | # ========================= | ||||
200 | sub initOptions() { | ||||
201 | my ($attributes) = @_; | ||||
202 | my %params = &Foswiki::Func::extractParameters($attributes); | ||||
203 | |||||
204 | my @allOptions = keys %globalDefaults; | ||||
205 | |||||
206 | # Check attributes: | ||||
207 | @unknownParams= ( ); | ||||
208 | foreach my $option (keys %params) { | ||||
209 | push (@unknownParams, $option) unless grep(/^\Q$option\E$/, @allOptions); | ||||
210 | } | ||||
211 | return 0 if $#unknownParams != -1; | ||||
212 | |||||
213 | my $name = &getName(\%params); | ||||
214 | |||||
215 | # handle _DEFAULT option (_DEFAULT = descr) | ||||
216 | $params{'descr'} = $params{'_DEFAULT'} if defined $params{'_DEFAULT'}; | ||||
217 | |||||
218 | # handle templates: | ||||
219 | my $tmplName = $params{'template'}; | ||||
220 | $tmplName = $namedDefaults{$name}{'template'} unless defined $tmplName; | ||||
221 | $tmplName = ( &Foswiki::Func::getPreferencesValue("\U${pluginName}_TEMPLATE\E") || undef) unless defined $tmplName; | ||||
222 | |||||
223 | # Setup options (attributes>named defaults>plugin preferences>global defaults): | ||||
224 | %options = ( ); | ||||
225 | foreach my $option (@allOptions) { | ||||
226 | my $v = $params{$option}; | ||||
227 | $v = $namedDefaults{$name}{$option} unless defined $v; | ||||
228 | if ((defined $tmplName)&&(!defined $v)) { | ||||
229 | $v = (&Foswiki::Func::getPreferencesFlag("\U${pluginName}_TEMPLATE_${tmplName}_${option}\E") || undef) if grep /^\Q$option\E$/, @flagOptions; | ||||
230 | $v = (&Foswiki::Func::getPreferencesValue("\U${pluginName}_TEMPLATE_${tmplName}_${option}\E") || undef) unless defined $v; | ||||
231 | $v = undef if (defined $v) && ($v eq ""); | ||||
232 | } | ||||
233 | |||||
234 | if (defined $v) { | ||||
235 | if (grep /^\Q$option\E$/, @flagOptions) { | ||||
236 | $options{$option} = ($v!~/(false|no|off|0|disable)/i); | ||||
237 | } else { | ||||
238 | $options{$option} = $v; | ||||
239 | } | ||||
240 | } else { | ||||
241 | if (grep /^\Q$option\E$/, @flagOptions) { | ||||
242 | $v = ( Foswiki::Func::getPreferencesFlag("\U${pluginName}_$option\E") || undef ); | ||||
243 | } else { | ||||
244 | $v = Foswiki::Func::getPreferencesValue("\U${pluginName}_$option\E"); | ||||
245 | } | ||||
246 | $v = undef if (defined $v) && ($v eq ""); | ||||
247 | $options{$option}= (defined $v?$v:$globalDefaults{$option}); | ||||
248 | } | ||||
249 | } | ||||
250 | |||||
251 | # Render some options: | ||||
252 | foreach my $option (@renderedOptions) { | ||||
253 | next unless defined $options{$option}; | ||||
254 | if ($options{$option} !~ /^(\s|\ \;)*$/) { | ||||
255 | $options{$option}=~s/(<nop>|!)//sg; | ||||
256 | $options{$option}=&Foswiki::Func::expandCommonVariables($options{$option},$topic, $web); | ||||
257 | if (grep /^\Q$option\E$/,@listOptions) { | ||||
258 | my @newlist = ( ); | ||||
259 | foreach my $i (split /\|/,$options{$option}) { | ||||
260 | my $newval=&Foswiki::Func::renderText($i, $web); | ||||
261 | $newval=~s/\|/\¦\;/sg; | ||||
262 | push @newlist, $newval; | ||||
263 | } | ||||
264 | $options{$option}=join('|',@newlist); | ||||
265 | } else { | ||||
266 | $options{$option}=&Foswiki::Func::renderText($options{$option}, $web); | ||||
267 | } | ||||
268 | } | ||||
269 | } | ||||
270 | |||||
271 | # filter some options: | ||||
272 | foreach my $option (@filteredOptions) { | ||||
273 | next unless defined $options{$option}; | ||||
274 | if (grep /^\Q$option\E$/,@listOptions) { | ||||
275 | my @newlist = ( ) ; | ||||
276 | foreach my $i (split /\|/, $options{$option}) { | ||||
277 | my $newval = &substIllegalChars($i); | ||||
278 | $newval=~s/\|/\¦\;/sg; | ||||
279 | push @newlist, $newval; | ||||
280 | } | ||||
281 | $options{$option}=join('|',@newlist); | ||||
282 | } else { | ||||
283 | $options{$option}=&substIllegalChars($options{$option}); | ||||
284 | } | ||||
285 | } | ||||
286 | |||||
- - | |||||
289 | return 1; | ||||
290 | } | ||||
291 | # ========================= | ||||
292 | sub initNamedDefaults { | ||||
293 | my ($attributes) = @_; | ||||
294 | |||||
295 | my %params = Foswiki::Func::extractParameters($attributes); | ||||
296 | |||||
297 | my $name = &getName(\%params); | ||||
298 | |||||
299 | my $tmplName = (defined $params{'template'}?$params{'template'}:undef); | ||||
300 | $tmplName = ( &Foswiki::Func::getPreferencesValue("\U${pluginName}_TEMPLATE\E") || undef) unless defined $tmplName; | ||||
301 | # create named defaults (attributes>named defaults>global defaults): | ||||
302 | foreach my $default (keys %globalDefaults) { | ||||
303 | next if grep(/^\Q$default\E$/,@ignoreNamedDefaults); | ||||
304 | $namedDefaults{$name}{$default}= $params{$default} if defined $params{$default}; | ||||
305 | $namedDefaults{$name}{$default}= (&Foswiki::Func::getPreferencesValue("\U${pluginName}_TEMPLATE_${tmplName}_${default}\E") || undef) unless (!defined $tmplName) || (defined $params{$default}); | ||||
306 | |||||
307 | } | ||||
308 | } | ||||
309 | # ========================= | ||||
310 | sub initStates { | ||||
311 | my ($query) = @_; | ||||
312 | if ((!defined $itemsCollected{"$web.$topic"}) &&((defined $query->param('clpsc'))||(defined $query->param('clreset')))) { | ||||
313 | $itemsCollected{"$web.$topic"}=1; | ||||
314 | &collectAllChecklistItems() ; | ||||
315 | } | ||||
316 | # read item states: | ||||
317 | if (! $itemStatesRead{$options{'name'}}) { | ||||
318 | $itemStatesRead{$options{'name'}} = 1; | ||||
319 | &readChecklistItemStateTopic($idMapRef); | ||||
320 | } | ||||
321 | } | ||||
322 | # ========================= | ||||
323 | sub renderLegend { | ||||
324 | my $query = &Foswiki::Func::getCgiQuery(); | ||||
325 | my @states = split /\|/, $options{'states'}; | ||||
326 | my @icons = split /\|/, $options{'stateicons'}; | ||||
327 | my $legend.=qq@<noautolink>@; | ||||
328 | $legend.=qq@(@; | ||||
329 | foreach my $state (@states) { | ||||
330 | my $icon = shift @icons; | ||||
331 | my ($iconsrc) = &getImageSrc($icon); | ||||
332 | my $heState = &htmlEncode($state); | ||||
333 | $iconsrc="" unless defined $iconsrc; | ||||
334 | $legend.=$query->img({src=>$iconsrc, alt=>$heState, title=>$heState}); | ||||
335 | $legend.=qq@ - $heState @; | ||||
336 | } | ||||
337 | $legend.=qq@) @; | ||||
338 | $legend.=qq@</noautolink>@; | ||||
339 | return $legend; | ||||
340 | } | ||||
341 | # ========================= | ||||
342 | sub handleChecklist { | ||||
343 | my ($attributes, $refText) = @_; | ||||
344 | |||||
345 | Foswiki::Func::writeDebug("- ${pluginName}::handleChecklist($attributes,...refText...)") if $debug; | ||||
346 | |||||
347 | my $text=""; | ||||
348 | |||||
349 | &initNamedDefaults($attributes); | ||||
350 | |||||
351 | local(%options); | ||||
352 | return &createUnknownParamsMessage() unless &initOptions($attributes); | ||||
353 | |||||
354 | my $query = &Foswiki::Func::getCgiQuery(); | ||||
355 | my %params = &Foswiki::Func::extractParameters($attributes); | ||||
356 | my $name = &getName(\%params); | ||||
357 | |||||
358 | my @states = split /\|/, $options{'states'}; | ||||
359 | my @icons = split /\|/, $options{'stateicons'}; | ||||
360 | |||||
361 | |||||
362 | if ((defined $query->param('clreset'))&&(!$resetDone)) { | ||||
363 | &initStates($query); | ||||
364 | my $n=$query->param('clreset'); | ||||
365 | my $s=(defined $query->param('clresetst'))?$query->param('clresetst'):$states[0]; | ||||
366 | if (($options{'name'} eq $n)&&(grep(/^\Q$s\E$/s, @states))) { | ||||
367 | &doChecklistItemStateReset($n,$s,$refText); | ||||
368 | $resetDone=1; | ||||
369 | } | ||||
370 | } | ||||
371 | |||||
372 | return "" if $dryrun; | ||||
373 | |||||
374 | my $legend = $options{'showlegend'}?&renderLegend():""; | ||||
375 | |||||
376 | if (defined $options{'reset'} && !$options{'static'}) { | ||||
377 | $namedResetIds{$name}++; | ||||
378 | my $reset = $options{'reset'}; | ||||
379 | my $state = (split /\|/, $options{'states'})[0]; | ||||
380 | |||||
381 | if ($reset=~/\@(\S+)/s) { | ||||
382 | $state=$1; | ||||
383 | $reset=~s/\@\S+//s; | ||||
384 | } | ||||
385 | |||||
386 | my ($imgsrc) = &getImageSrc($reset); | ||||
387 | $imgsrc="" unless defined $imgsrc; | ||||
388 | |||||
389 | my $title=$reset; | ||||
390 | $title=~s/<\S+[^>]*\>//sg; # strip HTML | ||||
391 | $title=&htmlEncode($title); | ||||
392 | |||||
393 | my $action = &createResetAction($name, $state); | ||||
394 | |||||
395 | $text.=qq@<noautolink>@; | ||||
396 | |||||
397 | $text.=$query->a({name=>"reset${name}"}, ' ') if $options{'anchors'} && !$options{'useajax'}; | ||||
398 | $text.=$legend; | ||||
399 | my $linktext=""; | ||||
400 | my $imgparams = {title=>$title, alt=>$title, border=>0}; | ||||
401 | $$imgparams{src}=$imgsrc if (defined $imgsrc ); # && ($imgsrc!~/^\s*$/s); | ||||
402 | $linktext.=$query->img($imgparams); | ||||
403 | $linktext.=qq@ ${title}@ if ($title!~/^\s*$/i)&&($imgsrc ne ""); | ||||
404 | $action="javascript:submitItemStateChange('$action');" if $options{'useajax'} && ($state ne 'STATESEL'); | ||||
405 | my $id = &urlEncode("${name}_${state}_".$namedResetIds{$name}); | ||||
406 | if ($state eq 'STATESEL') { | ||||
407 | $text.=&createHiddenDirectResetSelectionDiv($namedResetIds{$name},$name,\@states,\@icons); | ||||
408 | $action="javascript:clpTooltipShow('CLP_SM_DIV_RESET_${name}_$namedResetIds{$name}', 'CLP_A_$id',".(10+int($options{'tooltipfixleft'})).",".(10+int($options{'tooltipfixtop'})).",true);"; | ||||
409 | } | ||||
410 | $text.=$query->a({href=>$action,id=>'CLP_A_'.$id}, $linktext); | ||||
411 | |||||
412 | $text.=qq@</noautolink>@; | ||||
413 | } else { | ||||
414 | $text.=$legend; | ||||
415 | } | ||||
416 | if (defined $options{hide}) { | ||||
417 | my $state=""; | ||||
418 | $state = $1 if ($options{hide}=~s/\@(\S+)//g); | ||||
419 | $state = "" if $state eq $options{hide}; | ||||
420 | $text .= $query->a({href=>"javascript: clpHideShowToggle('$options{name}','$state')"}, $options{hide}); | ||||
421 | } | ||||
422 | |||||
423 | return $text; | ||||
424 | } | ||||
425 | # ========================= | ||||
426 | sub createResetAction { | ||||
427 | my ($name, $state) = @_; | ||||
428 | my $action=&Foswiki::Func::getViewUrl($web,$topic); | ||||
429 | $action=~s/#.*$//s; | ||||
430 | $action.=&getUniqueUrlParam($action); | ||||
431 | |||||
432 | $action.=($action=~/\?/?';':'?'); | ||||
433 | $action.="clreset=".&urlEncode($name); | ||||
434 | $action.=";clresetst=".&urlEncode($state); | ||||
435 | $action.=';skin='.&urlEncode($options{'ajaxtopicstyle'}) if $options{'useajax'}; | ||||
436 | |||||
437 | $action.="#reset${name}" if $options{'anchors'} && !$options{'useajax'}; | ||||
438 | return $action; | ||||
439 | } | ||||
440 | # ========================= | ||||
441 | sub createHiddenDirectResetSelectionDiv { | ||||
442 | my ($id, $name, $statesRef, $iconsRef) = @_; | ||||
443 | my $selTxt =""; | ||||
444 | my $query = &Foswiki::Func::getCgiQuery(); | ||||
445 | $selTxt=$query->sup($query->a({-href=>"javascript:clpTooltipHide('CLP_SM_DIV_RESET_${name}_$id');"},'[X]')); | ||||
446 | for (my $i=0; $i<=$#$statesRef; $i++) { | ||||
447 | my $s = $$statesRef[$i]; | ||||
448 | my $action = &createResetAction($name, $s); | ||||
449 | $action="javascript:submitItemStateChange('$action');clpTooltipHide('CLP_SM_DIV_RESET_${name}_$id');" if $options{'useajax'}; | ||||
450 | my $imgsrc = (&getImageSrc($$iconsRef[$i]))[0]; | ||||
451 | my $imgalt = (defined $imgsrc)?"":$s; | ||||
452 | $imgsrc="" unless defined $imgsrc; | ||||
453 | $selTxt.=$query->a({-href=>$action,-title=>$s,-style=>'vertical-align:bottom;'}, | ||||
454 | $query->img({src=>$imgsrc,alt=>$imgalt,border=>0,style=>'cursor:move;vertical-align:bottom'})); | ||||
455 | $selTxt.=' '; | ||||
456 | } | ||||
457 | |||||
458 | return $query->div({-id=>"CLP_SM_DIV_RESET_${name}_$id", | ||||
459 | -style=>"visibility:hidden;position:absolute;top:0;left:0;z-index:2;font: normal 8pt sans-serif;padding: 3px; border: solid 1px; background-color: $options{'tooltipbgcolor'};" }, $selTxt); | ||||
460 | } | ||||
461 | # ========================= | ||||
462 | sub substAttributes { | ||||
463 | my ($attributes, $p) = @_; | ||||
464 | |||||
465 | my %attrHash = &Foswiki::Func::extractParameters($attributes); | ||||
466 | my %pHash = (defined $p?&Foswiki::Func::extractParameters($p):()); | ||||
467 | |||||
468 | foreach my $a (keys %attrHash) { | ||||
469 | $pHash{$a}=$attrHash{$a}; | ||||
470 | } | ||||
471 | my $attr =""; | ||||
472 | foreach my $a (keys %pHash) { | ||||
473 | $attr .= ' '.$a.'="'.$pHash{$a}.'"'; | ||||
474 | } | ||||
475 | |||||
476 | return '%CLI{'.$attr.'}%'; | ||||
477 | } | ||||
478 | # ========================= | ||||
479 | sub substItemLine { | ||||
480 | my ($l,$attribs)=@_; | ||||
481 | if ($l=~s/(\s+)\#(\S+)/$1/) { | ||||
482 | $attribs.=" id=\"$2\""; | ||||
483 | } | ||||
484 | |||||
485 | $idOffset++; | ||||
486 | |||||
487 | $namedIds{$options{name}} = 0 unless defined $namedIds{$options{name}}; | ||||
488 | |||||
489 | my $id = "CLP_HIDE_ID_".$options{name}.($namedIds{$options{name}} + $idOffset); | ||||
490 | my $name = "CLP_HIDE_NAME_".$options{name}; | ||||
491 | my @states = split /\|/, $options{'states'}; | ||||
492 | my $state = $$idMapRef{$options{name}}{$namedIds{$options{name}}+$idOffset}{state}; | ||||
493 | $state = $states[0] unless defined $state; | ||||
494 | my $class = "clp_hide_".$options{name}."_".$state; | ||||
495 | |||||
496 | if ($l=~/\%CLI{.*?}\%/) { | ||||
497 | $l=~s/\%CLI{(.*?)}\%/\%CLI{$1 $attribs}\%/g; | ||||
498 | $l=~s/^/<span id="$id" name="$name" class="$class">/; | ||||
499 | $l=~s/$/<\/span>/; | ||||
500 | } else { | ||||
501 | if (lc($options{'clipos'}) eq 'left') { | ||||
502 | ###$l=~s/^(\s+[\d\*]+)/"$1 \%CLI{$attribs}% "/e; | ||||
503 | $l=~s/^(\s+[\d\*]+)(.*)$/"$1 <span id=\"$id\" name=\"$name\" class=\"$class\">\%CLI{$attribs}\% $2<\/span>"/e; | ||||
504 | } else { | ||||
505 | ###$l=~s/^(\s+[\d\*]+.*?)$/"$1 \%CLI{$attribs}%"/e; | ||||
506 | $l=~s/^(\s+[\d\*]+)(.*?)$/"$1 <span id=\"$id\" name=\"$name\" class=\"$class\">$2 \%CLI{$attribs}\%<\/span>"/e; | ||||
507 | } | ||||
508 | } | ||||
509 | |||||
510 | return $l; | ||||
511 | }; | ||||
512 | # ========================= | ||||
513 | sub handleAutoChecklist { | ||||
514 | my ($attributes, $text) = @_; | ||||
515 | |||||
516 | Foswiki::Func::writeDebug("- ${pluginName}::handleAutoChecklist($attributes,...text...)") if $debug; | ||||
517 | |||||
518 | &initNamedDefaults($attributes); | ||||
519 | |||||
520 | local(%options); local($idOffset); | ||||
521 | return &createUnknownParamsMessage() unless &initOptions($attributes); | ||||
522 | |||||
523 | initStates(Foswiki::Func::getCgiQuery()); | ||||
524 | |||||
525 | handleStateChanges(); | ||||
526 | |||||
527 | |||||
528 | $text=~s/\%CLI(\{([^\}]*)\})?\%/&substAttributes($attributes, $2)/meg; | ||||
529 | $text=~s/^(\s+[\d\*]+.*?)$/&substItemLine($1,$attributes)/meg; | ||||
530 | $text=~s/([^\n]+?\s+)\#(\S+)/$1.&substAttributes($attributes, "id=\"$2\"")/meg; | ||||
531 | |||||
532 | if (lc($options{'pos'}) eq 'top' ) { | ||||
533 | $text="\%CHECKLIST{$attributes}\%\n$text"; | ||||
534 | } else { | ||||
535 | $text.="\n\%CHECKLIST{$attributes}\%"; | ||||
536 | } | ||||
537 | |||||
538 | return $text; | ||||
539 | |||||
540 | } | ||||
541 | # ========================= | ||||
542 | sub handleChecklistItem { | ||||
543 | my ($attributes, $text,$startOffset,$endOffset) = @_; | ||||
544 | |||||
545 | Foswiki::Func::writeDebug("- ${pluginName}::handleChecklistItem($attributes)") if $debug; | ||||
546 | |||||
547 | local(%options); | ||||
548 | return &createUnknownParamsMessage() unless &initOptions($attributes); | ||||
549 | |||||
550 | my $query = &Foswiki::Func::getCgiQuery(); | ||||
551 | |||||
552 | &initStates($query); | ||||
553 | |||||
554 | $namedIds{$options{'name'}}++ unless defined $options{'id'}; | ||||
555 | |||||
556 | &handleDescription($text, $startOffset, $endOffset); | ||||
557 | |||||
558 | my $name = $options{'name'}; | ||||
559 | my $id = $options{'id'}?$options{'id'}:$namedIds{$name}; | ||||
560 | my $last = $$idMapRef{$name}{$id}{'state'}; | ||||
561 | |||||
562 | if ((defined $query->param('clpsc'))&&(!$stateChangeDone)) { | ||||
563 | my ($id,$name,$lastState,$nextstate) = ($query->param('clpsc'),$query->param('clpscn'),$query->param('clpscls'),$query->param('clpscns')); | ||||
564 | if ($options{'name'} eq $name) { | ||||
565 | &doChecklistItemStateChange($id, $name, $lastState, $text, $nextstate) ; | ||||
566 | $stateChangeDone=1; | ||||
567 | } | ||||
568 | } | ||||
569 | |||||
570 | my $state = (defined $$idMapRef{$name}{$id}{'state'}) ? $$idMapRef{$name}{$id}{'state'} : (split(/\|/, $options{'states'}))[0]; | ||||
571 | my $timestamp = (defined $$idMapRef{$name}{$id}{'timestamp'}) ? $$idMapRef{$name}{$id}{'timestamp'} : getLogEntry($options{timestampformat},$id,$name,$last, $state); | ||||
572 | |||||
573 | $$idMapRef{$name}{$id}{'state'}=$state unless defined $$idMapRef{$name}{$id}{'state'}; | ||||
574 | $$idMapRef{$name}{$id}{'descr'}=$options{'descr'} if defined $options{'descr'}; | ||||
575 | $$idMapRef{$name}{$id}{'timestamp'}=$timestamp; | ||||
576 | |||||
577 | push(@{$$idOrderRef{$name}}, $id) unless grep(/^\Q$id\E$/,@{$$idOrderRef{$name}}); | ||||
578 | |||||
579 | return "" if $dryrun; | ||||
580 | |||||
581 | return &renderChecklistItem(); | ||||
582 | |||||
583 | } | ||||
584 | # ========================= | ||||
585 | sub handleDescription { | ||||
586 | my ($text, $startOffset, $endOffset) = @_; | ||||
587 | |||||
588 | my $si = $startOffset - $options{'descrcharlimit'}; | ||||
589 | $si = 0 if ($si < 0); | ||||
590 | my $textBefore = substr( $text, $si, $startOffset-$si); | ||||
591 | my $textAfter = substr($text, $endOffset+1, $options{'descrcharlimit'}); | ||||
592 | |||||
593 | $textBefore =~ /([^>\n\%]*)$/; | ||||
594 | $textBefore = $1 if defined $1; | ||||
595 | |||||
596 | $textAfter =~ /^([^<\n\%]*)/; | ||||
597 | $textAfter = $1 if defined $1; | ||||
598 | |||||
599 | my $descr = $$idMapRef{$options{'name'}}{$options{'id'}?$options{'id'}:$namedIds{$options{'name'}}}{'descr'}; | ||||
600 | unless ( (defined $options{'descr'}) || ((defined $descr)&&($descr!~/^\s*$/))) { | ||||
601 | $options{'descr'}=$options{'text'} if (defined $options{'text'})&&($options{'text'}!~/^\s*$/s); | ||||
602 | |||||
603 | my $text = $textBefore; | ||||
604 | $text.=" ... " if $textBefore !~ /^\s*$/; | ||||
605 | $text.=$textAfter; | ||||
606 | $text.=" ..." if $textAfter !~ /^\s*$/; | ||||
607 | $options{'descr'}=$text unless defined $options{'descr'}; | ||||
608 | |||||
609 | $options{'descr'}=~s/^\s{3,}[\*\d]//sg; ## remove lists | ||||
610 | $options{'descr'}=~s/\|/ /sg; ## remove tables | ||||
611 | $options{'descr'}=~s/<[\/]?[^>]+>/ /sg; ## remove HTML tags | ||||
612 | $options{'descr'}=~s/\%\w+[^\%]*\%/ /sg; ## remove variables | ||||
613 | |||||
614 | $options{'descr'}=~s/\s{2,}/ /g; ## remove multiple spaces | ||||
615 | $options{'descr'}=~s/^\s*//g; | ||||
616 | $options{'descr'}=~s/\s*$//g; | ||||
617 | |||||
618 | |||||
619 | }; | ||||
620 | $options{'descr'}=substr($options{'descr'},0,$options{'descrcharlimit'}) | ||||
621 | if (defined $options{'descr'})&&(length($options{'descr'})>$options{'descrcharlimit'}); | ||||
622 | } | ||||
623 | |||||
624 | # ========================= | ||||
625 | sub getNextState { | ||||
626 | my ($name, $lastState) = @_; | ||||
627 | my @states = split /\|/, $options{'states'}; | ||||
628 | my @icons = split /\|/, $options{'stateicons'}; | ||||
629 | |||||
630 | $lastState=$states[0] if ! defined $lastState; | ||||
631 | |||||
632 | my $state = $states[0]; | ||||
633 | my $icon = $icons[0]; | ||||
634 | for (my $i=0; $i<=$#states; $i++) { | ||||
635 | if ($states[$i] eq $lastState) { | ||||
636 | $state=($i<$#states)?$states[$i+1]:$states[0]; | ||||
637 | $icon=($i<$#states)?$icons[$i+1]:$icons[0]; | ||||
638 | last; | ||||
639 | } | ||||
640 | } | ||||
641 | Foswiki::Func::writeDebug("- ${pluginName}::getNextState($name, $lastState)=$state; allstates=".$options{states}) if $debug; | ||||
642 | |||||
643 | return ($state, $icon); | ||||
644 | |||||
645 | } | ||||
646 | # ========================= | ||||
647 | sub checkChangeAccessPermission { | ||||
648 | my ($name, $text) = @_; | ||||
649 | my $ret = 1; | ||||
650 | |||||
651 | my $perm = 'CHANGE'; | ||||
652 | my $checkTopic = $topic; | ||||
653 | unless (&Foswiki::Func::topicExists($web, &getClisTopicName($name))) { | ||||
654 | $perm='CREATE'; | ||||
655 | $checkTopic = &getClisTopicName($name); | ||||
656 | $text = undef; | ||||
657 | } | ||||
658 | |||||
659 | |||||
660 | my $mainWebName=&Foswiki::Func::getMainWebname(); | ||||
661 | my $user =Foswiki::Func::getWikiName(); | ||||
662 | $user = "$mainWebName.$user" unless $user =~ m/^$mainWebName\./; | ||||
663 | |||||
664 | if ( ! &Foswiki::Func::checkAccessPermission($perm, $user, $text, $checkTopic, $web)) { | ||||
665 | $ret = 0; | ||||
666 | |||||
667 | eval { require Foswiki::AccessControlException; }; | ||||
668 | if ($@) { | ||||
669 | Foswiki::Func::redirectCgiQuery(Foswiki::Func::getCgiQuery(),Foswiki::Func::getOopsUrl($web,$checkTopic,"oopsaccesschange")); | ||||
670 | } else { | ||||
671 | require Error; | ||||
672 | throw Foswiki::AccessControlException( | ||||
673 | $perm, | ||||
674 | $Foswiki::Plugins::SESSION->{user}, | ||||
675 | $checkTopic, $web, 'denied' | ||||
676 | ); | ||||
677 | } | ||||
678 | } | ||||
679 | return $ret; | ||||
680 | } | ||||
681 | # ========================= | ||||
682 | sub extractPerms { | ||||
683 | my ($text) = @_; | ||||
684 | my $perms; | ||||
685 | |||||
686 | $text="" unless defined $text; | ||||
687 | $perms=join("\n",grep /^\s+\*\s*Set (ALLOW|DENY).+/i,split(/\n/,$text)); | ||||
688 | |||||
689 | return $perms; | ||||
690 | } | ||||
691 | # ========================= | ||||
692 | sub doChecklistItemStateReset { | ||||
693 | my ($n, $state, $text) = @_; | ||||
694 | Foswiki::Func::writeDebug("- ${pluginName}::doChecklistItemStateReset($n,$state,...text...)") if $debug; | ||||
695 | |||||
696 | # access granted? | ||||
697 | return if ! &checkChangeAccessPermission($n, $text); | ||||
698 | |||||
699 | if (!defined $state) { | ||||
700 | my @states=split /\|/, $options{'states'}; | ||||
701 | $state=$states[0]; | ||||
702 | } | ||||
703 | foreach my $id (keys %{$$idMapRef{$n}}) { | ||||
704 | $$idMapRef{$n}{$id}{'timestamp'}=getLogEntry($options{timestampformat},$id,$n,$$idMapRef{$n}{$id}{'state'}, $state); | ||||
705 | $$idMapRef{$n}{$id}{'state'}=$state; | ||||
706 | } | ||||
707 | saveLog('reset', $n, 'any', $state) if $options{log} && !$saveDone; | ||||
708 | &saveChecklistItemStateTopic($n,&extractPerms($text)) if (!$saveDone) && (($saveDone=!$saveDone)); | ||||
709 | } | ||||
710 | # ========================= | ||||
711 | sub doChecklistItemStateChange { | ||||
712 | my ($id, $n, $lastState, $text, $nextstate) = @_; | ||||
713 | Foswiki::Func::writeDebug("- ${pluginName}::doChecklistItemStateChange($id,$n,$lastState,...text...)") if $debug; | ||||
714 | |||||
715 | # access granted? | ||||
716 | return if ! &checkChangeAccessPermission($n, $text); | ||||
717 | |||||
718 | # reload? | ||||
719 | return if ((defined $$idMapRef{$n}{$id}{'state'})&&($$idMapRef{$n}{$id}{'state'} ne $lastState)); | ||||
720 | |||||
721 | my $rns = (defined $nextstate?$nextstate:(&getNextState($n, $$idMapRef{$n}{$id}{'state'}))[0]); | ||||
722 | |||||
723 | $$idMapRef{$n}{$id}{'state'}=$rns; | ||||
724 | $$idMapRef{$n}{$id}{'timestamp'}=getLogEntry($options{timestampformat},$id, $n, $lastState, $nextstate); | ||||
725 | |||||
726 | &saveLog($id, $n, $lastState, $rns) if $options{log} && !$saveDone; | ||||
727 | &saveChecklistItemStateTopic($n,&extractPerms($text)) if (!$saveDone) && (($saveDone=!$saveDone)); | ||||
728 | } | ||||
729 | # ========================= | ||||
730 | sub createAction { | ||||
731 | my ($id, $name, $state, $nextstate) = @_; | ||||
732 | my $action=Foswiki::Func::getViewUrl($web,$topic); | ||||
733 | |||||
734 | # remove anchor: | ||||
735 | $action=~s/#.*$//i; | ||||
736 | |||||
737 | $action.=getUniqueUrlParam($action); | ||||
738 | |||||
739 | $action.=($action=~/\?/)?";":"?"; | ||||
740 | $action.="clpsc=".&urlEncode("$id"); | ||||
741 | $action.=";clpscn=".&urlEncode($name); | ||||
742 | $action.=";clpscls=".&urlEncode($state); | ||||
743 | $action.=";clpscns=".&urlEncode($nextstate) if defined $nextstate; | ||||
744 | $action.=';skin='.&urlEncode($options{'ajaxtopicstyle'}) if $options{'useajax'}; | ||||
745 | |||||
746 | my $query = &Foswiki::Func::getCgiQuery(); | ||||
747 | my %queryVars = $query->Vars(); | ||||
748 | foreach my $p (keys %queryVars) { | ||||
749 | $action.=";$p=".&urlEncode($queryVars{$p}) | ||||
750 | unless ($p =~ /^(clp.*|clreset.*|contenttype|skin)$/i)||(!$queryVars{$p}); | ||||
751 | } | ||||
752 | $action.="#$name$id" if $options{'anchors'} && (!$options{'useajax'}); | ||||
753 | |||||
754 | return $action; | ||||
755 | } | ||||
756 | # ========================= | ||||
757 | sub createTitle { | ||||
758 | my ($name,$state,$icon,$statesRef, $nextstate, $nextstateicon, $tId, $timestamp) = @_; | ||||
759 | ($nextstate, $nextstateicon) = &getNextState($name,$state) unless defined $nextstate; | ||||
760 | my $query = &Foswiki::Func::getCgiQuery(); | ||||
761 | my $title = $options{'tooltip'}; | ||||
762 | $title = $state unless defined $title; | ||||
763 | $title =~ s/\%STATE\%/$state/sg; | ||||
764 | $title =~ s/\%NEXTSTATE\%/$nextstate/esg; | ||||
765 | $title =~ s/\%STATECOUNT\%/($#$statesRef+1)/esg; | ||||
766 | $title =~ s/\%STATES\%/join(", ",@{$statesRef})/esg; | ||||
767 | $title =~ s/\%LEGEND\%/&renderLegend()/esg; | ||||
768 | $title =~ s/\%STATEICON\%/$query->img({alt=>$state,src=>(&getImageSrc($icon))[0]})/esg; | ||||
769 | $title =~ s/\%NEXTSTATEICON\%/$query->img({alt=>$nextstate,src=>(&getImageSrc($nextstateicon))[0]})/esg; | ||||
770 | $title =~ s/\%TIMESTAMP\%/$timestamp/esg; | ||||
771 | return $title; | ||||
772 | } | ||||
773 | # ========================= | ||||
774 | sub renderChecklistItem { | ||||
775 | Foswiki::Func::writeDebug("- ${pluginName}::renderChecklistItem()") if $debug; | ||||
776 | my $query = &Foswiki::Func::getCgiQuery(); | ||||
777 | my $text = ""; | ||||
778 | my $name = $options{'name'}; | ||||
779 | |||||
780 | my @states = split /\|/, $options{'states'}; | ||||
781 | my @icons = split /\|/, $options{'stateicons'}; | ||||
782 | |||||
783 | my $tId = $options{'id'}?$options{'id'}:$namedIds{$name}; | ||||
784 | |||||
785 | my $timestamp = $$idMapRef{$name}{$tId}{'timestamp'}; | ||||
786 | $timestamp = "" unless defined $timestamp; | ||||
787 | |||||
788 | my $state = (defined $$idMapRef{$name}{$tId}{'state'}) ? $$idMapRef{$name}{$tId}{'state'} : $states[0]; | ||||
789 | my $icon = $icons[0]; | ||||
790 | |||||
791 | for (my $i=0; $i<=$#states; $i++) { | ||||
792 | if ($states[$i] eq $state) { | ||||
793 | $icon=$icons[$i]; | ||||
794 | last; | ||||
795 | } | ||||
796 | } | ||||
797 | |||||
798 | my ($iconsrc,$textBef,$textAft)=&getImageSrc($icon); | ||||
799 | |||||
800 | my $stId = &substIllegalChars($tId); # substituted tId | ||||
801 | my $heState = &htmlEncode($state); # HTML encoded state | ||||
802 | my $ueState = &urlEncode($state); # URL encoded state | ||||
803 | my $uetId = &urlEncode($tId); # URL encoded tId | ||||
804 | |||||
805 | |||||
806 | my $action = &createAction($stId, $name, $state); | ||||
807 | |||||
808 | $text.=qq@<noautolink>@; | ||||
809 | |||||
810 | $text.=$query->comment('CLTABLEPLUGINSORTFIX:'); | ||||
811 | $text.=$query->div({-style=>"visibility:hidden;position:absolute;top:0;left:0;z-index:2;" },$heState); | ||||
812 | $text.=$query->comment(':CLTABLEPLUGINSORTFIX'); | ||||
813 | |||||
814 | $text.=$query->a({name=>"$name$uetId"}, ' ') if $options{'anchors'} && !$options{'useajax'}; | ||||
815 | |||||
816 | my $linktext=""; | ||||
817 | if (lc($options{'clipos'}) ne 'left') { | ||||
818 | $linktext.=$options{'text'}.' ' unless $options{'text'} =~ /^(\s|\ \;)*$/; | ||||
819 | } | ||||
820 | |||||
821 | my $title = &createTitle($name, $state, $icon, \@states, undef,undef,$tId, $timestamp); | ||||
822 | |||||
823 | $linktext.=qq@$textBef@ if $textBef; | ||||
824 | my $imgalt = (!defined $iconsrc)?$state:""; | ||||
825 | $iconsrc = "" unless defined $iconsrc; | ||||
826 | $linktext.=$query->img({-name=>"CLP_IMG_$name$uetId", -src=>$iconsrc, -border=>0, -alt=>$imgalt}); | ||||
827 | $linktext.=qq@$textAft@ if $textAft; | ||||
828 | if (lc($options{'clipos'}) eq 'left') { | ||||
829 | $linktext.=' '.$options{'text'} unless $options{'text'} =~ /^(\s|\ \;)*$/; | ||||
830 | } | ||||
831 | |||||
832 | my ($onmouseover, $onmouseout)=("",""); | ||||
833 | $action="javascript:submitItemStateChange('$action');" if $options{'useajax'}; | ||||
834 | $onmouseover="clpTooltipShow('CLP_TT_$name$uetId','CLP_A_$name$uetId',".(20+int($options{'tooltipfixleft'})).",".(20+int($options{'tooltipfixtop'})).",true);"; | ||||
835 | $onmouseout="clpTooltipHide('CLP_TT_$name$uetId');"; | ||||
836 | $text .= $query->div({-id=>"CLP_TT_$name$uetId",-style=>"visibility:hidden;position:absolute;top:0;left:0;z-index:2;font: normal 8pt sans-serif;padding: 3px; border: solid 1px; background-color: $options{'tooltipbgcolor'};"},$title); | ||||
837 | if ($options{'statesel'} && (!$options{'static'})) { | ||||
838 | $action="javascript:clpTooltipShow('CLP_SM_DIV_$name$uetId','CLP_A_$name$uetId',".(10+int($options{'tooltipfixleft'})).",".(10+int($options{'tooltipfixtop'})).",true);"; | ||||
839 | $text .= &createHiddenDirectSelectionDiv($uetId, $name, $state, $icon, \@states, \@icons, $tId, $timestamp); | ||||
840 | } | ||||
841 | $action = "javascript:;" if $options{'static'}; | ||||
842 | $text .= $query->a({-onmouseover=>$onmouseover,-onmouseout=>$onmouseout,-id=>"CLP_A_$name$uetId",-name=>"CLP_A_$name$uetId",-href=>$action}, $linktext); | ||||
843 | |||||
844 | $text.=qq@</noautolink>@; | ||||
845 | |||||
846 | return $text; | ||||
847 | } | ||||
848 | # ========================= | ||||
849 | sub createHiddenDirectSelectionDiv { | ||||
850 | my ($id, $name, $state, $icon, $statesRef, $iconsRef, $tId, $timestamp) = @_; | ||||
851 | my $text =""; | ||||
852 | |||||
853 | my $query = &Foswiki::Func::getCgiQuery(); | ||||
854 | my $sl=""; | ||||
855 | $sl.=$query->sup($query->a({-href=>"javascript:clpTooltipHide('CLP_SM_DIV_$name$id');", -title=>'close'},'[X]')); | ||||
856 | for (my $i=0; $i<=$#$statesRef; $i++) { | ||||
857 | my ($s, $ic) = ($$statesRef[$i], $$iconsRef[$i]); | ||||
858 | my $action = &createAction($id, $name, $state, $s); | ||||
859 | my $title = &createTitle($name,$state,$icon,$statesRef, $s, $ic, $tId, $timestamp); | ||||
860 | my $submitAction = ""; | ||||
861 | if ($options{'useajax'}) { | ||||
862 | $submitAction = "submitItemStateChange('$action');clpTooltipHide('CLP_SM_DIV_$name$id');"; | ||||
863 | $action="javascript:$submitAction"; | ||||
864 | } | ||||
865 | $text .= $query->div({-id=>"CLP_SM_TT_$name${id}_$i",-style=>"visibility:hidden;position:absolute;top:0;left:0;z-index:3;font: normal 8pt sans-serif;padding: 3px; border: solid 1px; background-color: $options{'tooltipbgcolor'};"},$title); | ||||
866 | my $imgsrc = (&getImageSrc($ic))[0]; | ||||
867 | my $imgalt = (defined $imgsrc)?"":$s; | ||||
868 | $imgsrc="" if !defined $imgsrc; | ||||
869 | $sl.=$query->a({ | ||||
870 | -id=>"CLP_SM_A_$name${id}_$i", | ||||
871 | -href=>"$action", | ||||
872 | -style=>'vertical-align:bottom;', | ||||
873 | -onmouseover=>"clpTooltipShow('CLP_SM_TT_$name${id}_$i','CLP_SM_IMG_$name${id}_$i',".(20+int($options{'tooltipfixleft'})).",".(20+int($options{'tooltipfixtop'})).");", | ||||
874 | -onmouseout=>"clpTooltipHide('CLP_SM_TT_$name${id}_$i');", | ||||
875 | }, | ||||
876 | $query->img({src=>$imgsrc,id=>"CLP_SM_IMG_$name${id}_$i",alt=>$imgalt,border=>0,style=>'vertical-align:bottom;cursor:move;'})); | ||||
877 | $sl.=' '; | ||||
878 | } | ||||
879 | |||||
880 | $text.= $query->div({-id=>"CLP_SM_DIV_$name$id", | ||||
881 | -style=>"visibility:hidden;position:absolute;top:0;left:0;z-index:2;font: normal 8pt sans-serif;padding: 3px; border: solid 1px; background-color: $options{'tooltipbgcolor'};"}, $sl); | ||||
882 | |||||
883 | return $text; | ||||
884 | } | ||||
885 | # ========================= | ||||
886 | sub getUniqueUrlParam { | ||||
887 | my ($url) = @_; | ||||
888 | my $r = 0; | ||||
889 | $r = rand(1000) while ($r <= 100); | ||||
890 | return (($url=~/\?/)?'&':'?').'clpid='.time().int($r); | ||||
891 | } | ||||
892 | # ========================= | ||||
893 | sub urlEncode { | ||||
894 | my ($txt)=@_; | ||||
895 | $txt=~s/([^A-Za-z0-9\$\-\_\.\+\!\*\'\(\)\,])/sprintf("%%%02X", ord($1))/seg if defined $txt; | ||||
896 | return $txt; | ||||
897 | } | ||||
898 | # ========================= | ||||
899 | sub htmlEncode { | ||||
900 | my ($txt)=@_; | ||||
901 | return "" unless defined $txt; | ||||
902 | $txt=~s/(["<>])/sprintf("&#%02X;", ord($1))/seg; | ||||
903 | |||||
904 | return $txt; | ||||
905 | } | ||||
906 | # ======================== | ||||
907 | sub substIllegalChars { | ||||
908 | my ($txt) = @_; | ||||
909 | $txt=~s/[^A-Za-z0-9\-\.\_]//sg if defined $txt; | ||||
910 | return $txt; | ||||
911 | } | ||||
912 | # ======================== | ||||
913 | sub getImageSrc { | ||||
914 | my ($txt)=@_; | ||||
915 | my ($src,$b,$a) = (undef, undef, undef); | ||||
916 | ##if ($txt=~/$(.*?)img[^>]+?src="([^">]+?)"[^>]*(.*)$/is) { | ||||
917 | if ($txt=~/^([^<]*)<img[^>]+?src="([^">]+?)"[^>]*>(.*)$/is) { | ||||
918 | ##$src=$1; | ||||
919 | ($b,$src,$a)=($1,$2,$3); | ||||
920 | } | ||||
921 | return ($src,$b,$a); | ||||
922 | } | ||||
923 | |||||
- - | |||||
926 | # ========================= | ||||
927 | sub readChecklistItemStateTopic { | ||||
928 | my ($idMapRef) = @_; | ||||
929 | my $clisTopicName = $options{'statetopic'}; | ||||
930 | Foswiki::Func::writeDebug("- ${pluginName}::readChecklistItemStateTopic($topic, $web): $clisTopicName") if $debug; | ||||
931 | |||||
932 | my $clisTopic = Foswiki::Func::readTopicText($web, $clisTopicName); | ||||
933 | |||||
934 | if ($clisTopic =~ /^http.*?\/oops/) { | ||||
935 | Foswiki::Func::redirectCgiQuery(Foswiki::Func::getCgiQuery(), $clisTopic); | ||||
936 | return; | ||||
937 | } | ||||
938 | |||||
939 | foreach my $line (split /[\r\n]+/, $clisTopic) { | ||||
940 | if ($line =~ /^\s*\|\s*([^\|\*\s]*)\s*\|\s*([^\|\*\s]*)\s*\|\s*([^\|\s]*)\s*\|(\s*([^\|]+)\s*\|)?(\s*([^\|]+)\s*\|)?\s*$/) { | ||||
941 | my ($name,$id,$state,$descr,$timestamp) = ($1,$2,$3,$5,$7); | ||||
942 | $$idMapRef{$name}{$id}{'state'}=$state; | ||||
943 | $$idMapRef{$name}{$id}{'descr'}=$descr; | ||||
944 | $$idMapRef{$name}{$id}{'timestamp'}=$timestamp; | ||||
945 | push(@{$$idOrderRef{$name}}, $id) unless grep(/^\Q$id\E$/,@{$$idOrderRef{$name}}); | ||||
946 | } | ||||
947 | } | ||||
948 | } | ||||
949 | # ========================= | ||||
950 | sub getClisTopicName { | ||||
951 | my ($name) = @_; | ||||
952 | return $namedDefaults{$name}{'statetopic'}?$namedDefaults{$name}{'statetopic'}:$globalDefaults{'statetopic'}; | ||||
953 | } | ||||
954 | # ========================= | ||||
955 | sub getName { | ||||
956 | my($paramsRef) = @_; | ||||
957 | my $name=&substIllegalChars($$paramsRef{'name'}) if defined $$paramsRef{'name'}; | ||||
958 | $name=$globalDefaults{'name'} unless defined $name; | ||||
959 | return $name; | ||||
960 | } | ||||
961 | # ========================= | ||||
962 | sub getLogEntry { | ||||
963 | my ($format, $id, $n, $laststate, $nextstate) = @_; | ||||
964 | my $logentry = Foswiki::Func::expandCommonVariables($format, $options{logtopic}, $web); | ||||
965 | |||||
966 | my @states = split /\|/, $options{'states'}; | ||||
967 | $logentry =~ s/%CLIID%/$id/g; | ||||
968 | $logentry =~ s/%STATE%/(defined $laststate?$laststate:$states[0])/eg; | ||||
969 | $logentry =~ s/%NEXTSTATE%/$nextstate/g; | ||||
970 | |||||
971 | return $logentry; | ||||
972 | } | ||||
973 | # ========================= | ||||
974 | sub saveLog { | ||||
975 | my ($id, $n, $laststate, $nextstate) = @_; | ||||
976 | |||||
977 | my $oopsUrl = &Foswiki::Func::setTopicEditLock($web, $options{logtopic}, 1); | ||||
978 | if ($oopsUrl) { | ||||
979 | &Foswiki::Func::redirectCgiQuery(Foswiki::Func::getCgiQuery(), $oopsUrl); | ||||
980 | return; | ||||
981 | } | ||||
982 | |||||
983 | my $logtopictext = Foswiki::Func::readTopicText($web, $options{logtopic}); | ||||
984 | if ($logtopictext =~ /^http.*?\/oops/) { | ||||
985 | Foswiki::Func::redirectCgiQuery(Foswiki::Func::getCgiQuery(), $logtopictext); | ||||
986 | return; | ||||
987 | } | ||||
988 | checkChangeAccessPermission($options{logtopic}, $logtopictext) || return; | ||||
989 | |||||
990 | |||||
991 | my $logentry = getLogEntry($options{logformat}, $id, $n, $laststate, $nextstate); | ||||
992 | |||||
993 | my $meta = ""; | ||||
994 | while ($logtopictext =~s /(%META(:[^{]+){[^}]+}%)//s) { | ||||
995 | $meta.=$1; | ||||
996 | } | ||||
997 | $logtopictext .= $logentry if $options{logpos} !~ /prepend/i; | ||||
998 | $logtopictext = $logentry . $logtopictext if $options{logpos} =~ /prepend/i; | ||||
999 | |||||
1000 | Foswiki::Func::saveTopicText($web, $options{logtopic}, "$meta\n$logtopictext", 1, !$options{'notify'}); | ||||
1001 | Foswiki::Func::setTopicEditLock($web, $options{logtopic}, 0); | ||||
1002 | |||||
1003 | |||||
1004 | } | ||||
1005 | # ========================= | ||||
1006 | sub saveChecklistItemStateTopic { | ||||
1007 | my ($name,$perm) = @_; | ||||
1008 | return if $name eq ""; | ||||
1009 | my $clisTopicName = &getClisTopicName($name); | ||||
1010 | |||||
1011 | Foswiki::Func::writeDebug("- ${pluginName}::saveChecklistItemStateTopic($name): $clisTopicName, ".$namedDefaults{$name}{'statetopic'}) if $debug; | ||||
1012 | my $oopsUrl = &Foswiki::Func::setTopicEditLock($web, $clisTopicName, 1); | ||||
1013 | if ($oopsUrl) { | ||||
1014 | &Foswiki::Func::redirectCgiQuery(Foswiki::Func::getCgiQuery(), $oopsUrl); | ||||
1015 | return; | ||||
1016 | } | ||||
1017 | my $installWeb = $Foswiki::cfg{SystemWebName}; | ||||
1018 | my $topicText = ""; | ||||
1019 | $topicText.="%RED% WARNING! THIS TOPIC IS GENERATED BY $installWeb.$pluginName PLUGIN. DO NOT EDIT THIS TOPIC (except table data)!%ENDCOLOR%\n"; | ||||
1020 | $topicText.=qq@%BR%Back to the \[\[$web.$topic\]\[checklist topic $topic\]\].\n\n@; | ||||
1021 | foreach my $n ( sort keys %{ $idMapRef } ) { | ||||
1022 | next if ($clisTopicName ne $globalDefaults{'statetopic'})&&((!defined $namedDefaults{$n}{'statetopic'})||($clisTopicName ne $namedDefaults{$n}{'statetopic'})); | ||||
1023 | next if (($namedDefaults{$n}{'statetopic'})&&($clisTopicName ne $namedDefaults{$n}{'statetopic'})); | ||||
1024 | |||||
1025 | my $states = ($name eq $n)?$options{'states'}:undef; | ||||
1026 | $states = $namedDefaults{$n}{'states'} unless defined $states && $states ne ""; | ||||
1027 | $states = &Foswiki::Func::getPreferencesValue("\U$pluginName\E_STATES") unless defined $states && $states ne ""; | ||||
1028 | $states = $globalDefaults{'states'} unless defined $states && $states ne ""; | ||||
1029 | my $statesel = join ", ", (split /\|/, $states); | ||||
1030 | $topicText.="\n"; | ||||
1031 | $topicText.=qq@%EDITTABLE{format="|text,20,$n|text,10,|select,1,$statesel|textarea,2,|"}%\n@; | ||||
1032 | $topicText.=qq@%TABLE{footerrows="1"}%\n@; | ||||
1033 | $topicText.="|*context*|*id*|*state*|*description*|*timestamp*|\n"; | ||||
1034 | |||||
1035 | ###foreach my $id (sort keys %{ $$idMapRef{$n}}) { | ||||
1036 | ###foreach my $id (@{ $$idOrderRef{$n}}) { | ||||
1037 | my @arr = $#{$$idOrderRef{$n}}!=-1 ? @{$$idOrderRef{$n}} : sort(keys(%{$$idMapRef{$n}})); | ||||
1038 | foreach my $id (@arr) { | ||||
1039 | $topicText.="|$n|".&htmlEncode($id)."|".&htmlEncode($$idMapRef{$n}{$id}{'state'}) | ||||
1040 | .'| '.&htmlEncode($$idMapRef{$n}{$id}{'descr'}) | ||||
1041 | .'| '.&htmlEncode($$idMapRef{$n}{$id}{'timestamp'}) | ||||
1042 | ." |\n"; | ||||
1043 | } | ||||
1044 | $topicText.=qq@| *$n* | *statistics:* | *%CALC{"\$COUNTITEMS(R2:C\$COLUMN()..R\$ROW(-1):C\$COLUMN())"}%* | *entries: %CALC{"\$ROW(-2)"}%* ||\n@; | ||||
1045 | } | ||||
1046 | if ($perm) { | ||||
1047 | $topicText.="\nAccess rights inherited from $web.$topic:\n\n"; | ||||
1048 | $topicText.="\n$perm\n" if $perm; | ||||
1049 | } | ||||
1050 | $topicText.="\n-- $installWeb.$pluginName - ".&Foswiki::Func::formatTime(time(), "rcs")."\n"; | ||||
1051 | Foswiki::Func::saveTopicText($web, $clisTopicName, $topicText, 1, !$options{'notify'}); | ||||
1052 | Foswiki::Func::setTopicEditLock($web, $clisTopicName, 0); | ||||
1053 | } | ||||
1054 | # ========================= | ||||
1055 | sub createUnknownParamsMessage { | ||||
1056 | my $msg=""; | ||||
1057 | $msg = Foswiki::Func::getPreferencesValue('UNKNOWNPARAMSMSG') || undef; | ||||
1058 | $msg = $globalDefaults{'unknownparamsmsg'} unless defined $msg; | ||||
1059 | $msg =~ s/\%UNKNOWNPARAMSLIST\%/join(', ', sort @unknownParams)/eg; | ||||
1060 | $msg =~ s/\%KNOWNPARAMSLIST\%/join(', ', sort keys %globalDefaults)/eg; | ||||
1061 | |||||
1062 | return $msg; | ||||
1063 | } | ||||
1064 | # ========================= | ||||
1065 | sub collectAllChecklistItems { | ||||
1066 | ## never ever local($initText, $idMapRef, $idOrderRef, %itemsCollected, %itemStatesRead, $web, $topic) | ||||
1067 | local($dryrun, %namedDefaults, %namedIds, %namedResetIds, @unknownParams, $resetDone,$stateChangeDone,$saveDone ); | ||||
1068 | |||||
1069 | Foswiki::Func::writeDebug( "- ${pluginName}::collectAllChecklistItems()" ) if $debug; | ||||
1070 | |||||
1071 | my $text = $initText; | ||||
1072 | |||||
1073 | # prevent changes: | ||||
1074 | $resetDone=1; $stateChangeDone=1; | ||||
1075 | |||||
1076 | # prevent rendering: | ||||
1077 | $dryrun=1; | ||||
1078 | |||||
1079 | &handleAllTags($text, $topic, $web); | ||||
1080 | |||||
1081 | Foswiki::Func::writeDebug( "- ${pluginName}::collectAllChecklistItems() done!" ) if $debug; | ||||
1082 | } | ||||
1083 | # ========================= | ||||
1084 | # spent 433µs (137+296) within Foswiki::Plugins::ChecklistPlugin::postRenderingHandler which was called 5 times, avg 87µs/call:
# 5 times (137µs+296µs) by Foswiki::Plugin::invoke at line 294 of /var/www/foswiki11/lib/Foswiki/Plugin.pm, avg 87µs/call | ||||
1085 | 5 | 8µs | 5 | 38µs | my $query = Foswiki::Func::getCgiQuery(); # spent 38µs making 5 calls to Foswiki::Func::getCgiQuery, avg 8µs/call |
1086 | 5 | 22µs | if (defined $query) { | ||
1087 | 5 | 21µs | 5 | 183µs | my $startTag=$query->comment('CLTABLEPLUGINSORTFIX:'); # spent 92µs making 1 call to CGI::AUTOLOAD
# spent 90µs making 4 calls to CGI::comment, avg 23µs/call |
1088 | 5 | 11µs | 5 | 56µs | my $endTag=$query->comment(':CLTABLEPLUGINSORTFIX'); # spent 56µs making 5 calls to CGI::comment, avg 11µs/call |
1089 | 5 | 33µs | $_[0]=~s/\Q$startTag\E.*?\Q$endTag\E//sg; | ||
1090 | } | ||||
1091 | } | ||||
1092 | # ========================= | ||||
1093 | sub endRenderingHandler { | ||||
1094 | return postRenderingHandler( @_ ); | ||||
1095 | } | ||||
1096 | # ========================= | ||||
1097 | sub handleStateChanges { | ||||
1098 | |||||
1099 | my ($text) = @_; | ||||
1100 | my $query = &Foswiki::Func::getCgiQuery(); | ||||
1101 | if ((defined $query->param('clpsc'))&&(!$stateChangeDone)) { | ||||
1102 | my ($id,$name,$lastState,$nextstate) = ($query->param('clpsc'),$query->param('clpscn'),$query->param('clpscls'),$query->param('clpscns')); | ||||
1103 | if ($options{'name'} eq $name) { | ||||
1104 | &doChecklistItemStateChange($id, $name, $lastState, $text, $nextstate) ; | ||||
1105 | $stateChangeDone=1; | ||||
1106 | } | ||||
1107 | } | ||||
1108 | my @states = split /\|/, $options{'states'}; | ||||
1109 | if ((defined $query->param('clreset'))&&(!$resetDone)) { | ||||
1110 | my $n=$query->param('clreset'); | ||||
1111 | my $s=(defined $query->param('clresetst'))?$query->param('clresetst'):$states[0]; | ||||
1112 | if (($options{'name'} eq $n)&&(grep(/^\Q$s\E$/s, @states))) { | ||||
1113 | &doChecklistItemStateReset($n,$s,$text); | ||||
1114 | $resetDone=1; | ||||
1115 | } | ||||
1116 | } | ||||
1117 | } | ||||
1118 | 1 | 4µs | 1; | ||
1119 |