← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 18:42:36 2015
Reported on Fri Jul 31 18:48:14 2015

Filename/var/www/foswikidev/core/lib/Foswiki/Configure/Value.pm
StatementsExecuted 20 statements in 1.85ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
11118µs47µsFoswiki::Configure::Value::::BEGIN@68Foswiki::Configure::Value::BEGIN@68
11114µs33µsFoswiki::Configure::Value::::BEGIN@54Foswiki::Configure::Value::BEGIN@54
1119µs14µsFoswiki::Configure::Value::::BEGIN@55Foswiki::Configure::Value::BEGIN@55
1119µs34µsFoswiki::Configure::Value::::BEGIN@59Foswiki::Configure::Value::BEGIN@59
1114µs4µsFoswiki::Configure::Value::::BEGIN@61Foswiki::Configure::Value::BEGIN@61
1114µs4µsFoswiki::Configure::Value::::BEGIN@64Foswiki::Configure::Value::BEGIN@64
1114µs4µsFoswiki::Configure::Value::::BEGIN@65Foswiki::Configure::Value::BEGIN@65
1113µs3µsFoswiki::Configure::Value::::BEGIN@57Foswiki::Configure::Value::BEGIN@57
0000s0sFoswiki::Configure::Value::::CHECK_optionFoswiki::Configure::Value::CHECK_option
0000s0sFoswiki::Configure::Value::::_CHECKFoswiki::Configure::Value::_CHECK
0000s0sFoswiki::Configure::Value::::_FEEDBACKFoswiki::Configure::Value::_FEEDBACK
0000s0sFoswiki::Configure::Value::::_MANDATORYFoswiki::Configure::Value::_MANDATORY
0000s0sFoswiki::Configure::Value::::decodeValueFoswiki::Configure::Value::decodeValue
0000s0sFoswiki::Configure::Value::::encodeValueFoswiki::Configure::Value::encodeValue
0000s0sFoswiki::Configure::Value::::find_also_dependenciesFoswiki::Configure::Value::find_also_dependencies
0000s0sFoswiki::Configure::Value::::getAllValueKeysFoswiki::Configure::Value::getAllValueKeys
0000s0sFoswiki::Configure::Value::::getExpandedValueFoswiki::Configure::Value::getExpandedValue
0000s0sFoswiki::Configure::Value::::getPathFoswiki::Configure::Value::getPath
0000s0sFoswiki::Configure::Value::::getRawValueFoswiki::Configure::Value::getRawValue
0000s0sFoswiki::Configure::Value::::getSectionObjectFoswiki::Configure::Value::getSectionObject
0000s0sFoswiki::Configure::Value::::getValueObjectFoswiki::Configure::Value::getValueObject
0000s0sFoswiki::Configure::Value::::isFormattedTypeFoswiki::Configure::Value::isFormattedType
0000s0sFoswiki::Configure::Value::::newFoswiki::Configure::Value::new
0000s0sFoswiki::Configure::Value::::parseTypeParamsFoswiki::Configure::Value::parseTypeParams
0000s0sFoswiki::Configure::Value::::searchFoswiki::Configure::Value::search
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# See bottom of file for license and copyright information
2
3=pod
4
5---+ package Foswiki::Configure::Value
6
7A Value object is a Foswiki::Configure::Item that represents a single entry
8in a configuration spec i.e. it is the leaf type in a configuration
9model.
10
11Note that this object does *not* store the actual value of a configuration
12item. This object is the *model* only.
13
14---++ Value Attributes
15Values may have attributes associated with them in the .spec file. These
16attributes are identified by UPPERCASE names and may be one of four types:
17
18 * boolean - a single name enables the option.
19 * string - a name followed by an equals sign, followed by a quoted string
20 (single or double quotes both supported)
21 * keyword - a name followed by a keyword
22
23The special prefix 'NO' on any attribute name will clear the value of
24that attributes.
25
26In support of older .spec files, the following are also supported (though
27their usage is deprecated):
28
29 * Single-character attribute H. This is synonymous with HIDDEN.
30 * Single-character attribute M is ignored.
31 * Unquoted conditions - DISPLAY_IF and ENABLE_IF may be followed by a
32 a space, and terminated by /DISPLAY_IF (or /ENABLE_IF) or the end of
33 the string.
34
35Formally,
36
37attrs ::= attr attrs ;
38attr ::= name '=' values | name ;
39values ::= value | values ';' fattr ;
40value ::= quoted-string | name ;
41name is made up of [-A-Z0-9]
42
43Certain attributes define a 'process' that allows further parsing of the
44value of an attribute. A process is a ref to a function that performs
45this parsing. Execution of processes may be supressed by setting
46$Foswiki::Configure::LoadSpec::RAW_VALS to 1.
47
48Processes are used to parse 'FEEDBACK' and 'CHECK' values.
49
50=cut
51
52package Foswiki::Configure::Value;
53
54228µs252µs
# spent 33µs (14+19) within Foswiki::Configure::Value::BEGIN@54 which was called: # once (14µs+19µs) by Foswiki::Configure::LoadSpec::BEGIN@62 at line 54
use strict;
# spent 33µs making 1 call to Foswiki::Configure::Value::BEGIN@54 # spent 19µs making 1 call to strict::import
55223µs218µs
# spent 14µs (9+4) within Foswiki::Configure::Value::BEGIN@55 which was called: # once (9µs+4µs) by Foswiki::Configure::LoadSpec::BEGIN@62 at line 55
use warnings;
# spent 14µs making 1 call to Foswiki::Configure::Value::BEGIN@55 # spent 4µs making 1 call to warnings::import
56
57223µs13µs
# spent 3µs within Foswiki::Configure::Value::BEGIN@57 which was called: # once (3µs+0s) by Foswiki::Configure::LoadSpec::BEGIN@62 at line 57
use Data::Dumper ();
# spent 3µs making 1 call to Foswiki::Configure::Value::BEGIN@57
58
59232µs260µs
# spent 34µs (9+26) within Foswiki::Configure::Value::BEGIN@59 which was called: # once (9µs+26µs) by Foswiki::Configure::LoadSpec::BEGIN@62 at line 59
use Assert;
# spent 34µs making 1 call to Foswiki::Configure::Value::BEGIN@59 # spent 26µs making 1 call to Exporter::import
60
61239µs14µs
# spent 4µs within Foswiki::Configure::Value::BEGIN@61 which was called: # once (4µs+0s) by Foswiki::Configure::LoadSpec::BEGIN@62 at line 61
use Foswiki::Configure::Item ();
# spent 4µs making 1 call to Foswiki::Configure::Value::BEGIN@61
6218µsour @ISA = ('Foswiki::Configure::Item');
63
64220µs14µs
# spent 4µs within Foswiki::Configure::Value::BEGIN@64 which was called: # once (4µs+0s) by Foswiki::Configure::LoadSpec::BEGIN@62 at line 64
use Foswiki::Configure::FileUtil ();
# spent 4µs making 1 call to Foswiki::Configure::Value::BEGIN@64
65257µs14µs
# spent 4µs within Foswiki::Configure::Value::BEGIN@65 which was called: # once (4µs+0s) by Foswiki::Configure::LoadSpec::BEGIN@62 at line 65
use Foswiki::Configure::Reporter ();
# spent 4µs making 1 call to Foswiki::Configure::Value::BEGIN@65
66
67# Options valid in a .spec for a leaf value
68115µs129µs
# spent 47µs (18+29) within Foswiki::Configure::Value::BEGIN@68 which was called: # once (18µs+29µs) by Foswiki::Configure::LoadSpec::BEGIN@62 at line 85
use constant ATTRSPEC => {
# spent 29µs making 1 call to constant::import
69 CHECK => { handler => '_CHECK' },
70 CHECKER => {},
71 CHECK_ON_CHANGE => {},
72 DISPLAY_IF => { openclose => 1 },
73 ENABLE_IF => { openclose => 1 },
74 EXPERT => {},
75 FEEDBACK => { handler => '_FEEDBACK' },
76 HIDDEN => {},
77 MULTIPLE => {}, # Allow multiple select
78 SPELLCHECK => {},
79 LABEL => {},
80 ONSAVE => {}, # Call Checker->onSave() when set.
81
82 # Rename single character options (legacy)
83 H => 'HIDDEN',
84 M => { handler => '_MANDATORY' }
8511.60ms147µs};
# spent 47µs making 1 call to Foswiki::Configure::Value::BEGIN@68
86
87# Legal options for a CHECK. The number indicates the number of expected
88# parameters; -1 means '0 or more'
8917µsour %CHECK_options = (
90 also => -1, # List of other items to check when this is changed
91 authtype => 1, # for URLs
92 filter => 1, # filter exclude files when checking file permissions
93 iff => 1, # perl condition controlling when to check
94 max => 1, # max value
95 min => 1, # min value
96 trail => 0, # ignore trailing / when checking URL
97 undefok => 0, # is undef OK?
98 emptyok => 0, # is '' OK?
99 parts => -1, # for URL
100 partsreq => -1, # for URL
101 perms => -1, # file permissions
102 schemes => -1, # for URL
103 user => -1, # for URL
104 pass => -1, # for URL
105);
106
10711µsour %rename_options = ( nullok => 'undefok' );
108
109=begin TML
110
111---++ ClassMethod new($typename, %options)
112 * =$typename= e.g 'STRING', name of one of the Foswiki::Configure::TypeUIs
113 Defaults to 'UNKNOWN' if not given ('', 0 or undef).
114
115Constructor.
116
117*IMPORTANT NOTE*
118
119When constructing value objects in Pluggables, bear in mind that the
120=default= value is stored as *an unparsed perl string*. This string
121is checked for valid perl during the .spec load, but otherwise
122stored verbatim. It must be evaled to get the 'actual' default
123value.
124
125The presence of the key (tested using 'exists') indicates whether a
126default is provided or not. undef is a valid default.
127
128=cut
129
130sub new {
131 my ( $class, $typename, @options ) = @_;
132
133 my $this = $class->SUPER::new(
134 typename => ( $typename || 'UNKNOWN' ),
135 keys => '',
136
137 # We do not give it a value here, because the presence of
138 # the key indicates that a default is provided.
139 #default => undef,
140 @options
141 );
142 $this->{CHECK} ||= {};
143 $this->{CHECK}->{undefok} = 0
144 unless defined $this->{CHECK}->{undefok};
145 $this->{CHECK}->{emptyok} = 1
146 unless defined $this->{CHECK}->{emptyok}; # required for legacy
147
148 return $this;
149}
150
151# Return true if this value is one of the preformatted types. Values for
152# these types transfer verbatim from the UI to the LocalSite.cfg
153sub isFormattedType {
154 my $this = shift;
155 return $this->{typename} eq 'PERL';
156}
157
158sub parseTypeParams {
159 my ( $this, $str ) = @_;
160
161 if ( $this->{typename} =~ m/^(SELECT|BOOLGROUP)/ ) {
162
163 # SELECT types *always* start with a comma-separated list of
164 # things to select from. These things may be words or wildcard
165 # class specifiers, or quoted strings (no internal quotes)
166 my @picks = ();
167 do {
168 if ( $str =~ s/^(["'])(.*?)\1// ) {
169 push( @picks, $2 );
170 }
171 elsif ( $str =~ s/^([-A-Za-z0-9:.*]+)// || $str =~ m/(\s)*,/ ) {
172 my $v = $1;
173 $v = '' unless defined $v;
174 if ( $v =~ m/\*/ && $this->{typename} eq 'SELECTCLASS' ) {
175
176 # Populate the class list
177 push( @picks,
178 Foswiki::Configure::FileUtil::findPackages($v) );
179 }
180 else {
181 push( @picks, $v );
182 }
183 }
184 else {
185 die "Illegal .spec at '$str'";
186 }
187 } while ( $str =~ s/\s*,\s*// );
188 $this->{select_from} = [@picks];
189 }
190 elsif ( $str =~ s/^\s*(\d+(?:x\d+)?)// ) {
191
192 # Width specifier for e.g. STRING
193 $this->{SIZE} = $1;
194 }
195 return $str;
196}
197
198# A feedback is a set of key=value pairs
199sub _FEEDBACK {
200 my ( $this, $str ) = @_;
201
202 $str =~ s/^\s*(["'])(.*)\1\s*$/$2/;
203
204 my %fb;
205 while ( $str =~ s/^\s*([a-z]+)\s*=\s*// ) {
206
207 my $attr = $1;
208
209 if ( $str =~ s/^(\d+)// ) {
210
211 # name=number
212 $fb{$attr} = $1;
213 }
214 elsif ( $str =~ s/(["'])(.*?[^\\])\1// ) {
215
216 # name=string
217 $fb{$attr} = $2;
218 }
219 last unless $str =~ s/^\s*;//;
220 }
221
222 die "FEEDBACK parse failed at $str" unless $str =~ m/^\s*$/;
223
224 push @{ $this->{FEEDBACK} }, \%fb;
225}
226
227# Spec file options are:
228# CHECK="option option:value option:value,value option:'value'", where
229# * each option has a value (the default when just the keyword is
230# present is 1)
231# * options are separated by whitespace
232# * values are introduced by : and delimited by , (Unless quoted,
233# in which case there is just one value. N.B. If quoted, double \.)
234# * Generated an arrayref containing all values for
235# each option
236#
237# Multiple CHECK clauses allow default checkers to do several checks
238# for an item.
239# For example, DataDir wants one set of options for .txt files, and
240# another for ,v files.
241
242sub _CHECK {
243 my ( $this, $str ) = @_;
244
245 my $ostr = $str;
246 $str =~ s/^(["'])\s*(.*?)\s*\1$/$2/;
247
248 my %options;
249 while ( $str =~ s/^\s*([a-zA-Z][a-zA-Z0-9]*)// ) {
250 my $name = $1;
251 my $set = 1;
252 if ( $name =~ s/^no//i ) {
253 $set = 0; # negated option
254 }
255 $name = $rename_options{$name} if exists $rename_options{$name};
256 die "CHECK parse failed: unrecognised option '$name'"
257 unless ( defined $CHECK_options{$name} );
258
259 my @opts;
260 if ( $str =~ s/^\s*:\s*// ) {
261 do {
262 if ( $str =~ s/^(["'])(.*?[^\\])\1// ) {
263 push( @opts, $2 );
264 }
265 elsif ( $str =~ s/^([-+]?\d+)// ) {
266 push( @opts, $1 );
267 }
268 elsif ( $str =~ s/^([a-z_{}]+)//i ) {
269 push( @opts, $1 );
270 }
271 else {
272 die "CHECK parse failed: not a list at $str in $ostr";
273 }
274 } while ( $str =~ s/^\s*,\s*// );
275 }
276 if ( $CHECK_options{$name} >= 0
277 && scalar(@opts) != $CHECK_options{$name} )
278 {
279 die
280"CHECK parse failed: wrong number of params to '$name' (expected $CHECK_options{$name}, saw @opts)";
281 }
282 if ( !$set && scalar(@opts) != 0 ) {
283 die "CHECK parse failed: 'no$name' is not allowed";
284 }
285 if ( scalar(@opts) == 0 ) {
286 $this->{CHECK}->{$name} = $set;
287 }
288 else {
289 $this->{CHECK}->{$name} = \@opts;
290 }
291 }
292 die "CHECK parse failed, expected name at $str in $ostr"
293 if $str !~ /^\s*$/;
294}
295
296# M => CHECK="noemptyok noundefok"
297sub _MANDATORY {
298 my $this = shift;
299 $this->{CHECK}->{emptyok} = 0;
300 $this->{CHECK}->{undefok} = 0;
301}
302
303# A value is a leaf, so this is a NOP.
304sub getSectionObject {
305 return;
306}
307
308=begin TML
309
310---++ ObjectMethod getValueObject($keys)
311This is a leaf object, so there's no recursive search to be done; we just
312return $this if the keys match.
313
314=cut
315
316sub getValueObject {
317 my ( $this, $keys ) = @_;
318
319 return ( $this->{keys} && $keys eq $this->{keys} ) ? $this : undef;
320}
321
322sub getAllValueKeys {
323 my $this = shift;
324 return ( $this->{keys} );
325}
326
327=begin TML
328
329---++ ObjectMethod getRawValue() -> $rawval
330
331Get the current value of the key from $Foswiki::cfg.
332The value returned is not expanded (embedded $Foswiki::cfg references
333will be intact)
334
335=cut
336
337sub getRawValue {
338 my ($this) = @_;
339
340 if (DEBUG) {
341 my $path = \%Foswiki::cfg;
342 my $x = $this->{keys};
343 ASSERT( defined $x );
344 my $p = '$Foswiki::cfg';
345 while ( $x =~ s/^{(.*?)}// ) {
346 $path = $path->{$1};
347 $p .= "{$1}";
348
349 #print STDERR "$this->{keys} is undefined at $p"
350 # unless defined $path;
351 }
352 }
353 return eval("\$Foswiki::cfg$this->{keys}");
354}
355
356=begin TML
357
358---++ ObjectMethod getExpandedValue() -> $expandedval
359
360Get the current value of the key from $Foswiki::cfg.
361The value returned with embedded $Foswiki::cfg references
362recursively expanded. If the current value is undef, then undef
363is returned. Embedded references that evaluate to undef
364are expanded using the string 'undef'.
365
366=cut
367
368sub getExpandedValue {
369 my ( $this, $name ) = @_;
370
371 my $val = $this->getRawValue();
372 return undef unless defined $val;
373 Foswiki::Configure::Load::expandValue($val);
374 return $val;
375}
376
377=begin TML
378
379---++ ObjectMethod encodeValue($raw_value) -> $encoded_value
380
381Encode a "real" cfg value as a string (if necessary) for passing
382to other tools, such as UIs, in a type-sensitive way.
383
384=cut
385
386# THIS IS NOT THE SAME AS Foswiki::Configure::Reporter::uneval.
387# This function is returning a string that can be passed back to
388# a UI and then recycled back as a new value. As such the resultant
389# value requires type information to be correctly interpreted.
390#
391# uneval is producing a *perl expression* which, when evaled,
392# will yield the correct value, and doesn't need any type information.
393
394sub encodeValue {
395 my ( $this, $value ) = @_;
396
397 return undef unless defined $value;
398
399 if ( ref($value) eq 'Regexp' ) {
400
401 # Convert to string
402 $value = "$value";
403
404 # Strip off useless furniture (?^: ... )
405 $value =~ s/^\(\?\^:(.*)\)$/$1/;
406 return $value;
407 }
408 elsif ( ref($value) ) {
409 return Foswiki::Configure::Reporter::uneval( $value, 2 );
410 }
411 elsif ( $this->{typename} eq 'OCTAL' ) {
412 return sprintf( '0%o', $value );
413 }
414 elsif ( $this->{typename} eq 'BOOLEAN' ) {
415 return $value ? 1 : 0;
416 }
417
418 return $value;
419}
420
421=begin TML
422
423---++ ObjectMethod decodeValue($encoded_value) -> $raw_value
424
425Decode a string that represents the value (e.g a serialised perl structure)
426and return the 'true' value by applying type rules
427
428=cut
429
430sub decodeValue {
431 my ( $this, $value ) = @_;
432
433 # Empty string always interpreted as undef
434 return undef unless defined $value;
435
436 if ( $this->isFormattedType() ) {
437 $value = eval($value);
438 die $@ if $@;
439 }
440 elsif ( $this->{typename} eq 'OCTAL' ) {
441 $value = oct($value);
442 }
443 elsif ( $this->{typename} eq 'BOOLEAN' ) {
444 $value = $value ? 1 : 0;
445 }
446
447 # else String or number, just sling it back
448
449 return $value;
450}
451
452=begin TML
453
454---++ ObjectMethod CHECK_option($keyname) -> $value
455
456Return the first value of the first CHECK option that contains
457the key =$opt=
458
459e.g. if we have =CHECK="a b" CHECK="c d=99 e"= in the .spec
460then =CHECK_option('c')= will return true and
461=CHECK_option('d')= will return =99=
462
463=cut
464
465sub CHECK_option {
466 my ( $this, $opt ) = @_;
467 if ( ref( $this->{CHECK}->{$opt} ) eq 'ARRAY' ) {
468 return $this->{CHECK}->{$opt}->[0];
469 }
470 return $this->{CHECK}->{$opt};
471 return undef;
472}
473
474# Implements Foswiki::Configure::item
475sub search {
476 my ( $this, $re ) = @_;
477 if ( $this->{keys} =~ m/$re/i ) {
478 return ($this);
479 }
480 return ();
481}
482
483# Implements Foswiki::Configure::item
484sub getPath {
485 my $this = shift;
486 my @path;
487 @path = $this->{_parent}->getPath() if ( $this->{_parent} );
488 push( @path, $this->{keys} );
489 return @path;
490}
491
492# Implements Foswiki::Configure::Item
493sub find_also_dependencies {
494 my ( $this, $root ) = @_;
495 ASSERT($root) if DEBUG;
496
497 return unless $this->{CHECK_ON_CHANGE};
498 foreach my $slave ( split( /[\s,]+/, $this->{CHECK_ON_CHANGE} ) ) {
499 my $vob = $root->getValueObject($slave);
500 next unless ($vob);
501 my $check = $vob->{CHECK};
502 if ($check) {
503 $check->{also} ||= [];
504 push( @{ $check->{also} }, $slave );
505 }
506 else {
507 $vob->{CHECK} = { also => [$slave] };
508 }
509 }
510}
511
51216µs1;
513__END__