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

Filename/var/www/foswikidev/core/lib/Foswiki/Form/FieldDefinition.pm
StatementsExecuted 10 statements in 1.57ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
11125µs38µsFoswiki::Form::FieldDefinition::::BEGIN@18Foswiki::Form::FieldDefinition::BEGIN@18
11111µs35µsFoswiki::Form::FieldDefinition::::BEGIN@20Foswiki::Form::FieldDefinition::BEGIN@20
11110µs15µsFoswiki::Form::FieldDefinition::::BEGIN@19Foswiki::Form::FieldDefinition::BEGIN@19
1116µs6µsFoswiki::Form::FieldDefinition::::BEGIN@21Foswiki::Form::FieldDefinition::BEGIN@21
1115µs5µsFoswiki::Form::FieldDefinition::::BEGIN@23Foswiki::Form::FieldDefinition::BEGIN@23
0000s0sFoswiki::Form::FieldDefinition::::createMetaKeyValuesFoswiki::Form::FieldDefinition::createMetaKeyValues
0000s0sFoswiki::Form::FieldDefinition::::cssClassesFoswiki::Form::FieldDefinition::cssClasses
0000s0sFoswiki::Form::FieldDefinition::::finishFoswiki::Form::FieldDefinition::finish
0000s0sFoswiki::Form::FieldDefinition::::getDefaultValueFoswiki::Form::FieldDefinition::getDefaultValue
0000s0sFoswiki::Form::FieldDefinition::::getDisplayValueFoswiki::Form::FieldDefinition::getDisplayValue
0000s0sFoswiki::Form::FieldDefinition::::isEditableFoswiki::Form::FieldDefinition::isEditable
0000s0sFoswiki::Form::FieldDefinition::::isMandatoryFoswiki::Form::FieldDefinition::isMandatory
0000s0sFoswiki::Form::FieldDefinition::::isMultiValuedFoswiki::Form::FieldDefinition::isMultiValued
0000s0sFoswiki::Form::FieldDefinition::::isTextMergeableFoswiki::Form::FieldDefinition::isTextMergeable
0000s0sFoswiki::Form::FieldDefinition::::newFoswiki::Form::FieldDefinition::new
0000s0sFoswiki::Form::FieldDefinition::::populateMetaFromQueryDataFoswiki::Form::FieldDefinition::populateMetaFromQueryData
0000s0sFoswiki::Form::FieldDefinition::::renderForDisplayFoswiki::Form::FieldDefinition::renderForDisplay
0000s0sFoswiki::Form::FieldDefinition::::renderForEditFoswiki::Form::FieldDefinition::renderForEdit
0000s0sFoswiki::Form::FieldDefinition::::renderHiddenFoswiki::Form::FieldDefinition::renderHidden
0000s0sFoswiki::Form::FieldDefinition::::stringifyFoswiki::Form::FieldDefinition::stringify
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# base class for all form field types
3
4=begin TML
5
6---+ package Foswiki::Form::FieldDefinition
7
8Base class of all field definition classes.
9
10Type-specific classes are derived from this class to define specific
11per-type behaviours. This class also provides default behaviours for when
12a specific type cannot be loaded.
13
14=cut
15
16package Foswiki::Form::FieldDefinition;
17
18231µs252µs
# spent 38µs (25+13) within Foswiki::Form::FieldDefinition::BEGIN@18 which was called: # once (25µs+13µs) by Foswiki::Form::BEGIN@42 at line 18
use strict;
# spent 38µs making 1 call to Foswiki::Form::FieldDefinition::BEGIN@18 # spent 13µs making 1 call to strict::import
19227µs219µs
# spent 15µs (10+4) within Foswiki::Form::FieldDefinition::BEGIN@19 which was called: # once (10µs+4µs) by Foswiki::Form::BEGIN@42 at line 19
use warnings;
# spent 15µs making 1 call to Foswiki::Form::FieldDefinition::BEGIN@19 # spent 4µs making 1 call to warnings::import
20229µs260µs
# spent 35µs (11+25) within Foswiki::Form::FieldDefinition::BEGIN@20 which was called: # once (11µs+25µs) by Foswiki::Form::BEGIN@42 at line 20
use Assert;
# spent 35µs making 1 call to Foswiki::Form::FieldDefinition::BEGIN@20 # spent 25µs making 1 call to Exporter::import
21260µs16µs
# spent 6µs within Foswiki::Form::FieldDefinition::BEGIN@21 which was called: # once (6µs+0s) by Foswiki::Form::BEGIN@42 at line 21
use CGI ();
# spent 6µs making 1 call to Foswiki::Form::FieldDefinition::BEGIN@21
22
23
# spent 5µs within Foswiki::Form::FieldDefinition::BEGIN@23 which was called: # once (5µs+0s) by Foswiki::Form::BEGIN@42 at line 28
BEGIN {
2415µs if ( $Foswiki::cfg{UseLocale} ) {
25 require locale;
26 import locale();
27 }
2811.42ms15µs}
# spent 5µs making 1 call to Foswiki::Form::FieldDefinition::BEGIN@23
29
30=begin TML
31
32---++ ClassMethod new(%...)
33
34Construct a new FieldDefinition. Parameters are passed in a hash. See
35Form.pm for how it is called. Subclasses should pass @_ on to this class.
36
37=cut
38
39sub new {
40 my $class = shift;
41 my %attrs = @_;
42 ASSERT( $attrs{session} ) if DEBUG;
43
44 $attrs{name} ||= '';
45 $attrs{attributes} ||= '';
46 $attrs{description} ||= '';
47 $attrs{type} ||= ''; # default
48 $attrs{size} ||= '';
49 $attrs{size} =~ s/^\s*//;
50 $attrs{size} =~ s/\s*$//;
51 $attrs{validModifiers} ||= [];
52
53 return bless( \%attrs, $class );
54}
55
56=begin TML
57
58---++ ObjectMethod finish()
59Break circular references.
60
61=cut
62
63# Note to developers; please undef *all* fields in the object explicitly,
64# whether they are references or not. That way this method is "golden
65# documentation" of the live fields in the object.
66sub finish {
67 my $this = shift;
68
69 undef $this->{name};
70 undef $this->{type};
71 undef $this->{size};
72 undef $this->{value};
73 undef $this->{description};
74 undef $this->{attributes};
75 undef $this->{default};
76
77 undef $this->{session};
78}
79
80=begin TML
81
82---++ isEditable() -> $boolean
83
84Is the field type editable? Labels aren't, for example. Subclasses may need
85to redefine this.
86
87=cut
88
89sub isEditable { 1 }
90
91=begin TML
92
93---++ isMultiValued() -> $boolean
94
95Is the field type multi-valued (i.e. does it store multiple values)?
96Subclasses may need to redefine this.
97
98=cut
99
100sub isMultiValued { 0 }
101
102=begin TML
103
104---++ isTextMergeable() -> $boolean
105
106Is this field type mergeable using a conventional text merge?
107
108=cut
109
110# can't merge multi-valued fields (select+multi, checkbox)
111sub isTextMergeable { return !shift->isMultiValued() }
112
113=begin TML
114
115---++ isMandatory() -> $boolean
116
117Is this field mandatory (required)?
118
119=cut
120
121sub isMandatory { return shift->{attributes} =~ m/M/ }
122
123=begin TML
124
125---++ renderForEdit( $topicObject, $value ) -> ($col0html, $col1html)
126 =$topicObject= - the topic being edited
127Render the field for editing. Returns two chunks of HTML; the
128=$col0html= is appended to the HTML for the first column in the
129form table, and the =$col1html= is used as the content of the second column.
130
131=cut
132
133sub renderForEdit {
134 my ( $this, $topicObject, $value ) = @_;
135
136 # Treat like text, make it reasonably long, add a warning
137 return (
138 '<br /><span class="foswikiAlert">MISSING TYPE '
139 . $this->{type}
140 . '</span>',
141 CGI::textfield(
142 -class => $this->cssClasses('foswikiAlert foswikiInputField'),
143 -name => $this->{name},
144 -size => 80,
145 -override => 1,
146 -value => $value,
147 )
148 );
149}
150
151=begin TML
152
153---++ cssClasses(@classes) -> $classes
154Construct a list of the CSS classes for the form field. Adds additional
155class specifiers related to the attributes of the field e.g mandatory.
156Pass it a list of the other classnames you want on the field.
157
158=cut
159
160sub cssClasses {
161 my $this = shift;
162 if ( $this->isMandatory() ) {
163 push( @_, 'foswikiMandatory' );
164 }
165 return join( ' ', @_ );
166}
167
168=begin TML
169
170---++ getDefaultValue() -> $value
171Try and get a sensible default value for the field from the
172values stored in the form definition. The result should be
173a value string.
174
175Some subclasses may not support the definition of defaults in
176the form definition. In that case this method should return =undef=.
177
178=cut
179
180sub getDefaultValue {
181 my $this = shift;
182
183 my $value =
184 ( exists( $this->{default} ) ? $this->{default} : $this->{value} );
185 $value = '' unless defined $value; # allow 0 values
186
187 return $value;
188}
189
190=begin TML
191
192---++ renderHidden($meta) -> $html
193Render the form in =$meta= as a set of hidden fields.
194
195=cut
196
197sub renderHidden {
198 my ( $this, $meta ) = @_;
199
200 my $value;
201 if ( $this->{name} ) {
202 my $field = $meta->get( 'FIELD', $this->{name} );
203 $value = $field->{value};
204 }
205
206 my @values;
207
208 if ( defined($value) ) {
209 if ( $this->isMultiValued() ) {
210 push( @values, split( /\s*,\s*/, $value ) );
211 }
212 else {
213 push( @values, $value );
214 }
215 }
216 else {
217 $value = $this->getDefaultValue();
218 push( @values, $this->getDefaultValue() ) if $value;
219 }
220
221 return '' unless scalar(@values);
222
223 return CGI::hidden( -name => $this->{name}, -default => \@values );
224}
225
226=begin TML
227
228---++ ObjectMethod populateMetaDataFromQuery( $query, $meta, $old ) -> ($bValid, $bPresent)
229
230Given a CGI =$query=, a =$meta= object, and an array of =$old= field entries,
231then populate the $meta with a row for this field definition, taking the
232content from the query if it's there, otherwise from $old or failing that,
233from the default defined for the type. Refuses to update mandatory fields
234that have an empty value.
235
236Return $bValid true if the value in $meta was updated (either from the
237query or from a default in the form.
238Return $bPresent true if a value was present in the query (even it was undef)
239
240=cut
241
242sub populateMetaFromQueryData {
243 my ( $this, $query, $meta, $old ) = @_;
244 my $value;
245 my $bPresent = 0;
246
247 return unless $this->{name};
248
249 my %names = map { $_ => 1 } $query->multi_param;
250
251 if ( $names{ $this->{name} } ) {
252
253 # Field is present in the request
254 $bPresent = 1;
255 if ( $this->isMultiValued() ) {
256 my @values = $query->multi_param( $this->{name} );
257
258 if ( scalar(@values) == 1 && defined $values[0] ) {
259 @values = split( /,|%2C/, $values[0] );
260 }
261 my %vset = ();
262 foreach my $val (@values) {
263 $val ||= '';
264 $val =~ s/^\s*//;
265 $val =~ s/\s*$//;
266
267 # skip empty values
268 $vset{$val} = ( defined $val && $val =~ m/\S/ );
269 }
270 $value = '';
271 my $isValues = ( $this->{type} =~ m/\+values/ );
272
273 foreach my $option ( @{ $this->getOptions() } ) {
274 $option =~ s/^.*?[^\\]=(.*)$/$1/ if $isValues;
275
276 # Maintain order of definition
277 if ( $vset{$option} ) {
278 $value .= ', ' if length($value);
279 $value .= $option;
280 }
281 }
282 }
283 else {
284
285 # Default the value to the empty string (undef would result
286 # in the old value being restored)
287 # Note: we test for 'defined' because value can also be 0 (zero)
288 $value = $query->param( $this->{name} );
289 $value = '' unless defined $value;
290 if ( $this->{session}->inContext('edit') ) {
291 $value = Foswiki::expandStandardEscapes($value);
292 }
293 }
294 }
295
296 # Find the old value of this field
297 my $preDef;
298 foreach my $item (@$old) {
299 if ( $item->{name} eq $this->{name} ) {
300 $preDef = $item;
301 last;
302 }
303 }
304 my $def;
305
306 if ( defined($value) ) {
307
308 # mandatory fields must have length > 0
309 if ( $this->isMandatory() && length($value) == 0 ) {
310 return ( 0, $bPresent );
311 }
312
313 # NOTE: title and name are stored in the topic so that it can be
314 # viewed without reading in the form definition
315 my $title = $this->{title};
316 if ( $this->{definingTopic} ) {
317 $title = '[[' . $this->{definingTopic} . '][' . $title . ']]';
318 }
319 $def = $this->createMetaKeyValues(
320 $query, $meta,
321 {
322 name => $this->{name},
323 title => $title,
324 value => $value
325 }
326 );
327 }
328 elsif ($preDef) {
329 $def = $preDef;
330 }
331 else {
332 return ( 0, $bPresent );
333 }
334
335 $meta->putKeyed( 'FIELD', $def ) if $def;
336
337 return ( 1, $bPresent );
338}
339
340=begin TML
341
342---++ ObjectMethod createMetaKeyValues( $query, $meta, $keyvalues ) -> $keyvalues
343
344Create meta key/value pairs hash, to be overridden by subclasses.
345Default implementation passes all inputs unchanged.
346
347=cut
348
349sub createMetaKeyValues {
350
351 #my ( $this, $query, $meta, $keyvalues ) = @_;
352
353 return $_[3];
354}
355
356=begin TML
357
358---++ ObjectMethod renderForDisplay($format, $value, $attrs) -> $html
359
360Render the field for display, under the control of $attrs.
361
362(protected) means the resulting string is run through
363Foswiki::Render::protectFormFieldValue.
364
365 * =format= - the format to be expanded. The following tokens are available:
366 * =$title= - title of the form field. if this is not available
367 from the value, then the default title is taken from the form
368 field definition.
369 * =$value= - expanded to the (protected) value of the form field
370 *before mapping*
371 * =$value(display) - expanded to the (protected) value of the form
372 field *after* mapping
373 * =$attributes= - from the field definition
374 * =$type= - from the field definition
375 * =$size= - from the field definition
376 * =$definingTopic= - topic in which the field is defined
377 * =$value= - the scalar value of the field
378 * =$attrs= - attributes. Fields used are:
379 * =showhidden= - set to override H attribute
380 * =newline= - replace newlines with this (default &lt;br>)
381 * =bar= - replace vbar with this (default &amp;#124)
382 * =break= - boolean, set to hyphenate
383 * =protectdollar= - set to escape $
384 * =usetitle= - if set, use this for the title rather than the title
385 from the form definition
386
387=cut
388
389sub renderForDisplay {
390 my ( $this, $format, $value, $attrs ) = @_;
391
392 if ( !$attrs->{showhidden} ) {
393 my $fa = $this->{attributes} || '';
394 if ( $fa =~ m/H/ ) {
395 return '';
396 }
397 }
398
399 my $title = $this->{title}; # default
400 $title = $attrs->{usetitle} if defined $attrs->{usetitle};
401
402 require Foswiki::Render;
403
404 $format =~ s/\$title/$title/g;
405 if ( $format =~ m/\$value\(display\)/ ) {
406 my $vd = Foswiki::Render::protectFormFieldValue(
407 $this->getDisplayValue($value), $attrs );
408 $format =~ s/\$value\(display\)/$vd/g;
409 }
410 if ( $format =~ m/\$value/ ) {
411 my $v = Foswiki::Render::protectFormFieldValue( $value, $attrs );
412 $format =~ s/\$value/$v/g;
413 }
414 $format =~ s/\$name/$this->{name}/g;
415 $format =~ s/\$attributes/$this->{attributes}/g;
416 $format =~ s/\$type/$this->{type}/g;
417 $format =~ s/\$size/$this->{size}/g;
418 my $definingTopic = $this->{definingTopic} || 'FIELD';
419 $format =~ s/\$definingTopic/$definingTopic/g;
420
421 # remove nop exclamation marks from form field value before it is put
422 # inside a format like [[$topic][$formfield()]] that prevents it being
423 # detected
424 $format =~ s/!($Foswiki::regex{wikiWordRegex})/<nop>$1/gs;
425
426 return $format;
427}
428
429=begin TML
430
431---++ ObjectMethod getDisplayValue($value) -> $html
432
433Given a value for this form field, return the *mapped* value suitable for
434display. This is used when a form field must be displayed using a different
435format to the way the value is stored.
436
437The default does nothing.
438
439=cut
440
441sub getDisplayValue {
442 my ( $this, $value ) = @_;
443
444 return $value;
445}
446
447# Debug
448sub stringify {
449 my $this = shift;
450 my $s = '| '
451 . $this->{name} . ' | '
452 . $this->{type} . ' | '
453 . $this->{size} . ' | '
454 . $this->{attributes} . " |\n";
455 return $s;
456}
457
45813µs1;
459__END__