← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 19:05:14 2015
Reported on Fri Jul 31 19:08:11 2015

Filename/var/www/foswiki11/lib/Foswiki/Form/FieldDefinition.pm
StatementsExecuted 7 statements in 1.27ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
11116µs28µsFoswiki::Form::FieldDefinition::::BEGIN@18Foswiki::Form::FieldDefinition::BEGIN@18
11111µs16µsFoswiki::Form::FieldDefinition::::BEGIN@19Foswiki::Form::FieldDefinition::BEGIN@19
11110µs23µsFoswiki::Form::FieldDefinition::::BEGIN@20Foswiki::Form::FieldDefinition::BEGIN@20
0000s0sFoswiki::Form::FieldDefinition::::cssClassesFoswiki::Form::FieldDefinition::cssClasses
0000s0sFoswiki::Form::FieldDefinition::::finishFoswiki::Form::FieldDefinition::finish
0000s0sFoswiki::Form::FieldDefinition::::getDefaultValueFoswiki::Form::FieldDefinition::getDefaultValue
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µs241µs
# spent 28µs (16+13) within Foswiki::Form::FieldDefinition::BEGIN@18 which was called: # once (16µs+13µs) by Foswiki::Form::BEGIN@42 at line 18
use strict;
# spent 28µs making 1 call to Foswiki::Form::FieldDefinition::BEGIN@18 # spent 12µs making 1 call to strict::import
19224µs222µs
# spent 16µs (11+5) within Foswiki::Form::FieldDefinition::BEGIN@19 which was called: # once (11µs+5µs) by Foswiki::Form::BEGIN@42 at line 19
use warnings;
# spent 16µs making 1 call to Foswiki::Form::FieldDefinition::BEGIN@19 # spent 5µs making 1 call to warnings::import
2021.21ms236µs
# spent 23µs (10+13) within Foswiki::Form::FieldDefinition::BEGIN@20 which was called: # once (10µs+13µs) by Foswiki::Form::BEGIN@42 at line 20
use Assert;
# spent 23µs making 1 call to Foswiki::Form::FieldDefinition::BEGIN@20 # spent 13µs making 1 call to Assert::import
21
22=begin TML
23
24---++ ClassMethod new(%...)
25
26Construct a new FieldDefinition. Parameters are passed in a hash. See
27Form.pm for how it is called. Subclasses should pass @_ on to this class.
28
29=cut
30
31sub new {
32 my $class = shift;
33 my %attrs = @_;
34 ASSERT( $attrs{session} ) if DEBUG;
35
36 $attrs{name} ||= '';
37 $attrs{attributes} ||= '';
38 $attrs{type} ||= ''; # default
39 $attrs{size} ||= '';
40 $attrs{size} =~ s/^\s*//;
41 $attrs{size} =~ s/\s*$//;
42
43 return bless( \%attrs, $class );
44}
45
46=begin TML
47
48---++ ObjectMethod finish()
49Break circular references.
50
51=cut
52
53# Note to developers; please undef *all* fields in the object explicitly,
54# whether they are references or not. That way this method is "golden
55# documentation" of the live fields in the object.
56sub finish {
57 my $this = shift;
58
59 undef $this->{name};
60 undef $this->{attributes};
61 undef $this->{type};
62 undef $this->{size};
63 undef $this->{session};
64}
65
66=begin TML
67
68---++ isEditable() -> $boolean
69
70Is the field type editable? Labels aren't, for example. Subclasses may need
71to redefine this.
72
73=cut
74
75sub isEditable { 1 }
76
77=begin TML
78
79---++ isMultiValued() -> $boolean
80
81Is the field type multi-valued (i.e. does it store multiple values)?
82Subclasses may need to redefine this.
83
84=cut
85
86sub isMultiValued { 0 }
87
88=begin TML
89
90---++ isTextMergeable() -> $boolean
91
92Is this field type mergeable using a conventional text merge?
93
94=cut
95
96# can't merge multi-valued fields (select+multi, checkbox)
97sub isTextMergeable { return !shift->isMultiValued() }
98
99=begin TML
100
101---++ isMandatory() -> $boolean
102
103Is this field mandatory (required)?
104
105=cut
106
107sub isMandatory { return shift->{attributes} =~ /M/ }
108
109=begin TML
110
111---++ renderForEdit( $topicObject, $value ) -> ($col0html, $col1html)
112 =$topicObject= - the topic being edited
113Render the field for editing. Returns two chunks of HTML; the
114=$col0html= is appended to the HTML for the first column in the
115form table, and the =$col1html= is used as the content of the second column.
116
117=cut
118
119sub renderForEdit {
120 my ( $this, $topicObject, $value ) = @_;
121
122 # Treat like text, make it reasonably long, add a warning
123 return (
124 '<br /><span class="foswikiAlert">MISSING TYPE '
125 . $this->{type}
126 . '</span>',
127 CGI::textfield(
128 -class => $this->cssClasses('foswikiAlert foswikiInputField'),
129 -name => $this->{name},
130 -size => 80,
131 -value => $value
132 )
133 );
134}
135
136=begin TML
137
138---++ cssClasses(@classes) -> $classes
139Construct a list of the CSS classes for the form field. Adds additional
140class specifiers related to the attributes of the field e.g mandatory.
141Pass it a list of the other classnames you want on the field.
142
143=cut
144
145sub cssClasses {
146 my $this = shift;
147 if ( $this->isMandatory() ) {
148 push( @_, 'foswikiMandatory' );
149 }
150 return join( ' ', @_ );
151}
152
153=begin TML
154
155---++ getDefaultValue() -> $value
156Try and get a sensible default value for the field from the
157values stored in the form definition. The result should be
158a value string.
159
160Some subclasses may not support the definition of defaults in
161the form definition. In that case this method should return =undef=.
162
163=cut
164
165sub getDefaultValue {
166 my $this = shift;
167
168 my $value = $this->{value};
169 $value = '' unless defined $value; # allow 0 values
170
171 return $value;
172}
173
174=begin TML
175
176---++ renderHidden($meta) -> $html
177Render the form in =$meta= as a set of hidden fields.
178
179=cut
180
181sub renderHidden {
182 my ( $this, $meta ) = @_;
183
184 my $value;
185 if ( $this->{name} ) {
186 my $field = $meta->get( 'FIELD', $this->{name} );
187 $value = $field->{value};
188 }
189
190 my @values;
191
192 if ( defined($value) ) {
193 if ( $this->isMultiValued() ) {
194 push( @values, split( /\s*,\s*/, $value ) );
195 }
196 else {
197 push( @values, $value );
198 }
199 }
200 else {
201 $value = $this->getDefaultValue();
202 push( @values, $this->getDefaultValue() ) if $value;
203 }
204
205 return '' unless scalar(@values);
206
207 return CGI::hidden( -name => $this->{name}, -default => \@values );
208}
209
210=begin TML
211
212---++ populateMetaDataFromQuery( $query, $meta, $old ) -> ($bValid, $bPresent)
213
214Given a CGI =$query=, a =$meta= object, and an array of =$old= field entries,
215then populate the $meta with a row for this field definition, taking the
216content from the query if it's there, otherwise from $old or failing that,
217from the default defined for the type. Refuses to update mandatory fields
218that have an empty value.
219
220Return $bValid true if the value in $meta was updated (either from the
221query or from a default in the form.
222Return $bPresent true if a value was present in the query (even it was undef)
223
224=cut
225
226sub populateMetaFromQueryData {
227 my ( $this, $query, $meta, $old ) = @_;
228 my $value;
229 my $bPresent = 0;
230
231 return unless $this->{name};
232
233 my %names = map { $_ => 1 } $query->param;
234
235 if ( $names{ $this->{name} } ) {
236
237 # Field is present in the request
238 $bPresent = 1;
239 if ( $this->isMultiValued() ) {
240 my @values = $query->param( $this->{name} );
241
242 if ( scalar(@values) == 1 && defined $values[0] ) {
243 @values = split( /,|%2C/, $values[0] );
244 }
245 my %vset = ();
246 foreach my $val (@values) {
247 $val ||= '';
248 $val =~ s/^\s*//o;
249 $val =~ s/\s*$//o;
250
251 # skip empty values
252 $vset{$val} = ( defined $val && $val =~ /\S/ );
253 }
254 $value = '';
255 my $isValues = ( $this->{type} =~ /\+values/ );
256
257 foreach my $option ( @{ $this->getOptions() } ) {
258 $option =~ s/^.*?[^\\]=(.*)$/$1/ if $isValues;
259
260 # Maintain order of definition
261 if ( $vset{$option} ) {
262 $value .= ', ' if length($value);
263 $value .= $option;
264 }
265 }
266 }
267 else {
268
269 # Default the value to the empty string (undef would result
270 # in the old value being restored)
271 # Note: we test for 'defined' because value can also be 0 (zero)
272 $value = $query->param( $this->{name} );
273 $value = '' unless defined $value;
274 if ( $this->{session}->inContext('edit') ) {
275 $value = Foswiki::expandStandardEscapes($value);
276 }
277 }
278 }
279
280 # Find the old value of this field
281 my $preDef;
282 foreach my $item (@$old) {
283 if ( $item->{name} eq $this->{name} ) {
284 $preDef = $item;
285 last;
286 }
287 }
288 my $def;
289
290 if ( defined($value) ) {
291
292 # mandatory fields must have length > 0
293 if ( $this->isMandatory() && length($value) == 0 ) {
294 return ( 0, $bPresent );
295 }
296
297 # NOTE: title and name are stored in the topic so that it can be
298 # viewed without reading in the form definition
299 my $title = $this->{title};
300 if ( $this->{definingTopic} ) {
301 $title = '[[' . $this->{definingTopic} . '][' . $title . ']]';
302 }
303 $def = {
304 name => $this->{name},
305 title => $title,
306 value => $value,
307 attributes => $this->{attributes},
308 };
309 }
310 elsif ($preDef) {
311 $def = $preDef;
312 }
313 else {
314 return ( 0, $bPresent );
315 }
316
317 $meta->putKeyed( 'FIELD', $def ) if $def;
318
319 return ( 1, $bPresent );
320}
321
322=begin TML
323
324---++ ObjectMethod renderForDisplay($format, $attrs) -> $html
325
326Render the field for display, under the control of $attrs.
327
328The following vars in $format are expanded:
329 $title - title of the form field
330 $value - expanded to the *protected* value of the form field
331
332The value is protected by Foswiki::Render::protectFormFieldValue.
333
334=cut
335
336sub renderForDisplay {
337 my ( $this, $format, $value, $attrs ) = @_;
338
339 if ( !$attrs->{showhidden} ) {
340 my $fa = $this->{attributes} || '';
341 if ( $fa =~ /H/ ) {
342 return '';
343 }
344 }
345
346 require Foswiki::Render;
347 $value = Foswiki::Render::protectFormFieldValue( $value, $attrs );
348
349 $format =~ s/\$title/$this->{title}/g;
350 $format =~ s/\$value/$value/g;
351 $format =~ s/\$name/$this->{name}/g;
352 $format =~ s/\$attributes/$this->{attributes}/g;
353 $format =~ s/\$type/$this->{type}/g;
354 $format =~ s/\$size/$this->{size}/g;
355 my $definingTopic = $this->{definingTopic} || 'FIELD';
356 $format =~ s/\$definingTopic/$definingTopic/g;
357
358 return $format;
359}
360
361# Debug
362sub stringify {
363 my $this = shift;
364 my $s = '| '
365 . $this->{name} . ' | '
366 . $this->{type} . ' | '
367 . $this->{size} . ' | '
368 . $this->{attributes} . " |\n";
369 return $s;
370}
371
37212µs1;
373__END__