Filename | /var/www/foswikidev/core/lib/Foswiki/Configure/Checker.pm |
Statements | Executed 20 statements in 1.51ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 3.23ms | 3.37ms | BEGIN@36 | Foswiki::Configure::Checker::
1 | 1 | 1 | 13µs | 25µs | BEGIN@27 | Foswiki::Configure::Checker::
1 | 1 | 1 | 12µs | 24µs | BEGIN@292 | Foswiki::Configure::Checker::
1 | 1 | 1 | 10µs | 41µs | BEGIN@38 | Foswiki::Configure::Checker::
1 | 1 | 1 | 9µs | 14µs | BEGIN@28 | Foswiki::Configure::Checker::
1 | 1 | 1 | 9µs | 35µs | BEGIN@33 | Foswiki::Configure::Checker::
1 | 1 | 1 | 4µs | 4µs | BEGIN@35 | Foswiki::Configure::Checker::
1 | 1 | 1 | 3µs | 3µs | BEGIN@30 | Foswiki::Configure::Checker::
1 | 1 | 1 | 3µs | 3µs | BEGIN@31 | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | ERROR | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | NOTE | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | WARN | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | check | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | checkExpandedValue | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | checkGnuProgram | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | checkPerlModule | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | check_current_value | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | getCfg | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | getCfgUndefOk | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | getItemCurrentValue | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | getItemDefaultValue | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | loadChecker | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | new | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | setItemValue | Foswiki::Configure::Checker::
0 | 0 | 0 | 0s | 0s | warnAboutWindowsBackSlashes | Foswiki::Configure::Checker::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # See bottom of file for license and copyright information | ||||
2 | |||||
3 | =begin TML | ||||
4 | |||||
5 | ---+ package Foswiki::Configure::Checker; | ||||
6 | |||||
7 | Base class of all checkers. Checkers give checking and guessing support | ||||
8 | for configuration values. Checkers are designed to be totally independent | ||||
9 | of UI. | ||||
10 | |||||
11 | All 'Value' type configuration items in the model can have a checker. | ||||
12 | Further, if a value doesn't have an individual checker, there may | ||||
13 | be an associated type checker. If an item has an individual checker, | ||||
14 | it's type checker is *not* invoked. | ||||
15 | |||||
16 | A checker must provide =check_current_value=, as described below. | ||||
17 | |||||
18 | Checkers *never* modify =$Foswiki::cfg=. | ||||
19 | |||||
20 | Checker objects are not instantiated directly. Rather, they are generated | ||||
21 | using the =loadChecker= factory method described below. | ||||
22 | |||||
23 | =cut | ||||
24 | |||||
25 | package Foswiki::Configure::Checker; | ||||
26 | |||||
27 | 2 | 27µs | 2 | 38µs | # spent 25µs (13+13) within Foswiki::Configure::Checker::BEGIN@27 which was called:
# once (13µs+13µs) by Foswiki::Plugins::ConfigurePlugin::BEGIN@42 at line 27 # spent 25µs making 1 call to Foswiki::Configure::Checker::BEGIN@27
# spent 13µs making 1 call to strict::import |
28 | 2 | 27µs | 2 | 18µs | # spent 14µs (9+4) within Foswiki::Configure::Checker::BEGIN@28 which was called:
# once (9µs+4µs) by Foswiki::Plugins::ConfigurePlugin::BEGIN@42 at line 28 # spent 14µs making 1 call to Foswiki::Configure::Checker::BEGIN@28
# spent 4µs making 1 call to warnings::import |
29 | |||||
30 | 2 | 19µs | 1 | 3µs | # spent 3µs within Foswiki::Configure::Checker::BEGIN@30 which was called:
# once (3µs+0s) by Foswiki::Plugins::ConfigurePlugin::BEGIN@42 at line 30 # spent 3µs making 1 call to Foswiki::Configure::Checker::BEGIN@30 |
31 | 2 | 20µs | 1 | 3µs | # spent 3µs within Foswiki::Configure::Checker::BEGIN@31 which was called:
# once (3µs+0s) by Foswiki::Plugins::ConfigurePlugin::BEGIN@42 at line 31 # spent 3µs making 1 call to Foswiki::Configure::Checker::BEGIN@31 |
32 | |||||
33 | 2 | 33µs | 2 | 60µs | # spent 35µs (9+26) within Foswiki::Configure::Checker::BEGIN@33 which was called:
# once (9µs+26µs) by Foswiki::Plugins::ConfigurePlugin::BEGIN@42 at line 33 # spent 35µs making 1 call to Foswiki::Configure::Checker::BEGIN@33
# spent 26µs making 1 call to Exporter::import |
34 | |||||
35 | 2 | 20µs | 1 | 4µs | # spent 4µs within Foswiki::Configure::Checker::BEGIN@35 which was called:
# once (4µs+0s) by Foswiki::Plugins::ConfigurePlugin::BEGIN@42 at line 35 # spent 4µs making 1 call to Foswiki::Configure::Checker::BEGIN@35 |
36 | 2 | 110µs | 1 | 3.37ms | # spent 3.37ms (3.23+136µs) within Foswiki::Configure::Checker::BEGIN@36 which was called:
# once (3.23ms+136µs) by Foswiki::Plugins::ConfigurePlugin::BEGIN@42 at line 36 # spent 3.37ms making 1 call to Foswiki::Configure::Checker::BEGIN@36 |
37 | |||||
38 | 1 | 6µs | 1 | 31µs | # spent 41µs (10+31) within Foswiki::Configure::Checker::BEGIN@38 which was called:
# once (10µs+31µs) by Foswiki::Plugins::ConfigurePlugin::BEGIN@42 at line 42 # spent 31µs making 1 call to constant::import |
39 | I had to guess this setting in order to continue checking. You must | ||||
40 | confirm this setting (and any other guessed settings) and save | ||||
41 | correct values before changing any other settings. | ||||
42 | 1 | 819µs | 1 | 41µs | HERE # spent 41µs making 1 call to Foswiki::Configure::Checker::BEGIN@38 |
43 | |||||
44 | 1 | 200ns | my %checkers; | ||
45 | |||||
46 | # Construct a new Checker, attaching the given $item from the model. | ||||
47 | # This is not normally used by other classes, but is provided in case | ||||
48 | # a subclass needs to override it for any reason. | ||||
49 | sub new { | ||||
50 | my ( $class, $item ) = @_; | ||||
51 | |||||
52 | my $this = bless( { item => $item }, $class ); | ||||
53 | } | ||||
54 | |||||
55 | =begin TML | ||||
56 | |||||
57 | ---++ StaticMethod loadChecker($item [, $explicit]) -> $checker | ||||
58 | |||||
59 | Loads the Foswiki::Configure::Checker subclass for the | ||||
60 | given $item. For example, given the $item->{keys} '{Beans}{Mung}', it | ||||
61 | will try and load Foswiki::Configure::Checkers::Beans::Mung | ||||
62 | |||||
63 | An item may specify a different checker to load if it has the | ||||
64 | CHECKER attribute. This will be interpreted as keys for the 'real' checker | ||||
65 | to lead for this item. This behaviour is suppressed if $explicit is | ||||
66 | true (i.e. CHECKER will be ignored, and the default behaviour will apply. | ||||
67 | This is useful in the case where an explicit CHECKER has to chain the | ||||
68 | other checkers for an item.) | ||||
69 | |||||
70 | If the item doesn't have a subclass defined, the item's type class may | ||||
71 | define a generic checker for that type. If so, it is instantiated | ||||
72 | for this item. | ||||
73 | |||||
74 | Finally, we will see if $item's type, or one it inherits from | ||||
75 | has a generic checker. If so, that's instantiated. | ||||
76 | |||||
77 | Returns the checker that's created or undef if no such checker is found. | ||||
78 | |||||
79 | Will die if the checker exists but fails to compile. | ||||
80 | |||||
81 | $item is passed on to the checker's constructor. | ||||
82 | |||||
83 | =cut | ||||
84 | |||||
85 | sub loadChecker { | ||||
86 | my ( $item, $explicit ) = @_; | ||||
87 | my $id; | ||||
88 | |||||
89 | if ( !$explicit && $item->{CHECKER} ) { | ||||
90 | |||||
91 | # Checker override | ||||
92 | $id = $item->{CHECKER}; | ||||
93 | } | ||||
94 | else { | ||||
95 | ASSERT( $item && $item->{keys} ) if DEBUG; | ||||
96 | |||||
97 | # Convert {key}{s} to key::s, removing illegal characters | ||||
98 | # [-_\w] are legal. - => _. | ||||
99 | $id = $item->{keys}; | ||||
100 | |||||
101 | $id =~ s{\{([^\}]*)\}}{ | ||||
102 | my $lbl = $1; | ||||
103 | $lbl =~ tr,-_a-zA-Z0-9\x00-\xff,__a-zA-Z0-9,d; | ||||
104 | $lbl . '::'}ge | ||||
105 | and substr( $id, -2 ) = ''; | ||||
106 | } | ||||
107 | |||||
108 | foreach my $chkmod ( $id, $item->{typename} ) { | ||||
109 | if ( defined $checkers{$chkmod} ) { | ||||
110 | if ( $checkers{$chkmod} ) { | ||||
111 | |||||
112 | #print STDERR "Returning cached $chkmod\n"; | ||||
113 | return $checkers{$chkmod}->new($item); | ||||
114 | } | ||||
115 | } | ||||
116 | else { | ||||
117 | my $checkClass = 'Foswiki::Configure::Checkers::' . $chkmod; | ||||
118 | if ( | ||||
119 | Foswiki::Configure::FileUtil::findFileOnPath( | ||||
120 | $checkClass . '.pm' | ||||
121 | ) | ||||
122 | ) | ||||
123 | { | ||||
124 | eval("require $checkClass"); | ||||
125 | unless ($@) { | ||||
126 | $checkers{$chkmod} = $checkClass; | ||||
127 | |||||
128 | #print STDERR "Returning NEW cached $chkmod\n"; | ||||
129 | return $checkClass->new($item); | ||||
130 | } | ||||
131 | else { | ||||
132 | die "Checker $checkClass failed to load: $@\n"; | ||||
133 | } | ||||
134 | } | ||||
135 | |||||
136 | #print STDERR "Caching empty $chkmod\n"; | ||||
137 | $checkers{$chkmod} = ''; | ||||
138 | } | ||||
139 | } | ||||
140 | return undef; | ||||
141 | } | ||||
142 | |||||
143 | =begin TML | ||||
144 | |||||
145 | ---++ ObjectMethod check_current_value($reporter) | ||||
146 | * =$reporter= - report logger; use ERROR, WARN etc on this | ||||
147 | object to record information. | ||||
148 | |||||
149 | The value to be checked is taken from $Foswiki::cfg. This is the | ||||
150 | baseline check for values already in $Foswiki::cfg, and needs to | ||||
151 | be as fast as possible (it should not do any heavy processing). | ||||
152 | |||||
153 | Old checkers may not provide =check_current_value= but instead | ||||
154 | use the older signature =check=. | ||||
155 | |||||
156 | =cut | ||||
157 | |||||
158 | sub check_current_value { | ||||
159 | my ( $this, $reporter ) = @_; | ||||
160 | |||||
161 | # If we get all the way back up the inheritance tree without | ||||
162 | # finding a check_current_value implementation, then see if | ||||
163 | # there is a check(). | ||||
164 | if ( $this->can('check') ) { | ||||
165 | $this->{reporter} = $reporter; | ||||
166 | $this->check( $this->{item} ); | ||||
167 | delete $this->{reporter}; | ||||
168 | } | ||||
169 | } | ||||
170 | |||||
171 | ################################################################### | ||||
172 | # Compatibility methods | ||||
173 | # Note that ASSERT($this->{reporter} if DEBUG is used to confirm that | ||||
174 | # the call has come from an implementation of check() | ||||
175 | |||||
176 | # Get the value of the named configuration var. | ||||
177 | # * =$keys= - optional keys to retrieve e.g | ||||
178 | # =getCfg("{Validation}{ExpireKeyOnUse}")=. Defaults to the | ||||
179 | # keys of the item associated with the checker. | ||||
180 | # | ||||
181 | # Any embedded references to other Foswiki::cfg vars will be expanded. | ||||
182 | # Note that any embedded references to undefined variables will be | ||||
183 | # expanded as the string 'undef'. Use =getCfgUndefOk= if you want a | ||||
184 | # real undef for undefined values rather than the string. | ||||
185 | # | ||||
186 | # Synonymous with: | ||||
187 | # <verbatim> | ||||
188 | # my $x = '$Foswiki::cfg{Keys}'; | ||||
189 | # Foswiki::Configure::Load::expandValue($x, 0); | ||||
190 | # </verbatim> | ||||
191 | # Thus it returns the value as Foswiki will see it (i.e. with undef | ||||
192 | # expanded as the string 'undef') | ||||
193 | sub getCfg { | ||||
194 | my ( $this, $name ) = @_; | ||||
195 | $name ||= $this->{item}->{keys}; | ||||
196 | |||||
197 | my $item = '$Foswiki::cfg' . $name; | ||||
198 | Foswiki::Configure::Load::expandValue($item); | ||||
199 | return $item; | ||||
200 | } | ||||
201 | |||||
202 | # As =getCfg=, except that =undef= will not be expanded to the string 'undef'. | ||||
203 | # Note that recursive expansion of embedded =$Foswiki::cfg= will also return | ||||
204 | # undef, and will result in a program error. | ||||
205 | sub getCfgUndefOk { | ||||
206 | |||||
207 | my ( $this, $name, $undef ) = @_; | ||||
208 | $name ||= $this->{item}->{keys}; | ||||
209 | |||||
210 | my $item = '$Foswiki::cfg' . $name; | ||||
211 | Foswiki::Configure::Load::expandValue( $item, defined $undef ? $undef : 1 ); | ||||
212 | return $item; | ||||
213 | } | ||||
214 | |||||
215 | # Provided for compatibility; if a checker tries to call SUPER::check and | ||||
216 | # the superclass only has check_current_value, it will fold back to here. | ||||
217 | sub check { | ||||
218 | my ($this) = @_; | ||||
219 | |||||
220 | # Subclasses often use SUPER::check, so make sure it's there. | ||||
221 | # Passing the checker as the reporter is a bit of a hack, but | ||||
222 | # OK by design. | ||||
223 | ASSERT( $this->can('check_current_value') ) if DEBUG; | ||||
224 | $this->check_current_value($this); | ||||
225 | } | ||||
226 | |||||
227 | # Provided for use by check() implementations *only* new checkers | ||||
228 | # *must not* call this. | ||||
229 | sub NOTE { | ||||
230 | my $this = shift; | ||||
231 | ASSERT( $this->{reporter} ) if DEBUG; | ||||
232 | $this->{reporter}->NOTE(@_); | ||||
233 | return join( ' ', @_ ); | ||||
234 | } | ||||
235 | |||||
236 | # Provided for use by check() implementations *only* new checkers | ||||
237 | # *must not* call this. | ||||
238 | sub WARN { | ||||
239 | my $this = shift; | ||||
240 | ASSERT( $this->{reporter} ) if DEBUG; | ||||
241 | $this->{reporter}->WARN(@_); | ||||
242 | return join( ' ', @_ ); | ||||
243 | } | ||||
244 | |||||
245 | # Provided for use by check() implementations *only* new checkers | ||||
246 | # *must not* call this. | ||||
247 | sub ERROR { | ||||
248 | my $this = shift; | ||||
249 | ASSERT( $this->{reporter} ) if DEBUG; | ||||
250 | $this->{reporter}->ERROR(@_); | ||||
251 | return join( ' ', @_ ); | ||||
252 | } | ||||
253 | |||||
254 | # Set the value of the checked configuration var. | ||||
255 | # $keys are optional. | ||||
256 | # Provided for use by check() implementations *only* new checkers | ||||
257 | # *must not* call this. | ||||
258 | sub setItemValue { | ||||
259 | my ( $this, $value, $keys ) = @_; | ||||
260 | $keys ||= $this->{item}->{keys}; | ||||
261 | ASSERT( $this->{reporter} ) if DEBUG; | ||||
262 | |||||
263 | eval("\$Foswiki::cfg$keys = \$value;"); | ||||
264 | if ($@) { | ||||
265 | die "Unable to set value $value for $keys\n"; | ||||
266 | } | ||||
267 | return wantarray ? ( $keys, $value ) : $keys; | ||||
268 | } | ||||
269 | |||||
270 | # Provided for use by check() implementations *only* new checkers | ||||
271 | # *must not* call this. | ||||
272 | sub getItemCurrentValue { | ||||
273 | my $this = shift; | ||||
274 | my $keys = shift || $this->{item}->{keys}; | ||||
275 | ASSERT( $this->{reporter} ) if DEBUG; | ||||
276 | my $value = eval("\$Foswiki::cfg$keys"); | ||||
277 | if ($@) { | ||||
278 | die "Unable to get value for $keys\n"; | ||||
279 | } | ||||
280 | return $value; | ||||
281 | } | ||||
282 | |||||
283 | # Get the default value of the checked configuration var. | ||||
284 | # $keys is optional | ||||
285 | # Provided for use by check() implementations *only* new checkers | ||||
286 | # *must not* call this. | ||||
287 | sub getItemDefaultValue { | ||||
288 | my $this = shift; | ||||
289 | my $keys = shift || $this->{item}->{keys}; | ||||
290 | ASSERT( $this->{reporter} ) if DEBUG; | ||||
291 | |||||
292 | 2 | 431µs | 2 | 36µs | # spent 24µs (12+12) within Foswiki::Configure::Checker::BEGIN@292 which was called:
# once (12µs+12µs) by Foswiki::Plugins::ConfigurePlugin::BEGIN@42 at line 292 # spent 24µs making 1 call to Foswiki::Configure::Checker::BEGIN@292
# spent 12µs making 1 call to warnings::unimport |
293 | my $value = eval("\$$Foswiki::Configure::defaultCfg->$keys"); | ||||
294 | if ($@) { | ||||
295 | die "Unable to get default $value for $keys\n"; | ||||
296 | } | ||||
297 | return $value; | ||||
298 | } | ||||
299 | |||||
300 | # Provided for use by check() implementations *only* new checkers | ||||
301 | # *must not* call this. | ||||
302 | sub checkGnuProgram { | ||||
303 | my ( $this, $prog ) = @_; | ||||
304 | ASSERT( $this->{reporter} ) if DEBUG; | ||||
305 | Foswiki::Configure::FileUtil::checkGNUProgram( $prog, $this ); | ||||
306 | return ''; | ||||
307 | } | ||||
308 | |||||
309 | # Provided for use by check() implementations *only* new checkers | ||||
310 | # *must not* call this. | ||||
311 | sub checkPerlModule { | ||||
312 | my ( $this, $module, $note, $version ) = @_; | ||||
313 | ASSERT( $this->{reporter} ) if DEBUG; | ||||
314 | my %mod = ( | ||||
315 | name => $module, | ||||
316 | usage => $note, | ||||
317 | disposition => 'required', | ||||
318 | mimimumVersion => $version | ||||
319 | ); | ||||
320 | Foswiki::Configure::Dependency::checkPerlModules( \%mod ); | ||||
321 | if ( $mod{ok} ) { | ||||
322 | $this->{reporter}->NOTE( $mod{check_result} ); | ||||
323 | return ''; | ||||
324 | } | ||||
325 | else { | ||||
326 | $this->{reporter}->ERROR( $mod{check_result} ); | ||||
327 | return 'ERROR'; | ||||
328 | } | ||||
329 | } | ||||
330 | |||||
331 | ################################################################### | ||||
332 | # Support methods, used by subclasses | ||||
333 | |||||
334 | =begin TML | ||||
335 | |||||
336 | ---++ PROTECTED ObjectMethod warnAboutWindowsBackSlashes($path) -> $html | ||||
337 | |||||
338 | Generate a warning if the supplied pathname includes windows-style | ||||
339 | path separators. | ||||
340 | |||||
341 | PROVIDED FOR COMPATIBILITY ONLY - DO NOT USE! Use inheritance of | ||||
342 | Checkers::PATH behaviour instead. | ||||
343 | |||||
344 | =cut | ||||
345 | |||||
346 | sub warnAboutWindowsBackSlashes { | ||||
347 | my ( $this, $path ) = @_; | ||||
348 | if ( $path =~ m/\\/ ) { | ||||
349 | return $this->WARN( | ||||
350 | 'You should use c:/path style slashes, not c:\path in "' | ||||
351 | . $path | ||||
352 | . '"' ); | ||||
353 | } | ||||
354 | } | ||||
355 | |||||
356 | =begin TML | ||||
357 | |||||
358 | ---++ PROTECTED ObjectMethod checkExpandedValue($reporter) -> $value | ||||
359 | |||||
360 | Report the expanded value of a parameter. Return the expanded value. | ||||
361 | |||||
362 | =cut | ||||
363 | |||||
364 | sub checkExpandedValue { | ||||
365 | my ( $this, $reporter ) = @_; | ||||
366 | |||||
367 | my $raw = $this->{item}->getRawValue(); | ||||
368 | my $value = $this->{item}->getExpandedValue(); | ||||
369 | |||||
370 | my $field = $value; | ||||
371 | |||||
372 | if ( !defined $raw ) { | ||||
373 | $raw = 'undef'; | ||||
374 | } | ||||
375 | |||||
376 | if ( !defined $field ) { | ||||
377 | if ( !$this->{item}->CHECK_option('undefok') ) { | ||||
378 | $reporter->ERROR("May not be undefined"); | ||||
379 | } | ||||
380 | $field = 'undef'; | ||||
381 | } | ||||
382 | |||||
383 | if ( $field eq '' && !$this->{item}->CHECK_option('emptyok') ) { | ||||
384 | $reporter->ERROR("May not be empty"); | ||||
385 | } | ||||
386 | |||||
387 | if ( ref($field) ) { | ||||
388 | $field = $this->{item}->encodeValue($field); | ||||
389 | } | ||||
390 | |||||
391 | #print STDERR "field=$field, raw=$raw\n"; | ||||
392 | |||||
393 | if ( $field ne $raw ) { | ||||
394 | if ( $field =~ m/\n/ ) { | ||||
395 | $reporter->NOTE( 'Expands to: <verbatim>', $field, '</verbatim>' ); | ||||
396 | } | ||||
397 | elsif ( $field eq '' ) { | ||||
398 | $reporter->NOTE("Expands to: '' (empty)"); | ||||
399 | } | ||||
400 | else { | ||||
401 | $reporter->NOTE("Expands to: =$field="); | ||||
402 | } | ||||
403 | } | ||||
404 | |||||
405 | return $value; | ||||
406 | } | ||||
407 | |||||
408 | 1 | 3µs | 1; | ||
409 | __END__ |