File Coverage

blib/lib/HTML/FormFu/Element.pm
Criterion Covered Total %
statement 110 119 92.4
branch 30 32 93.7
condition 14 15 93.3
subroutine 34 41 82.9
pod 4 26 15.3
total 192 233 82.4


line stmt bran cond sub pod time code
1             package HTML::FormFu::Element;
2              
3 390     390   177452 use strict;
  390         521  
  390         15464  
4             our $VERSION = '2.05'; # VERSION
5              
6 390     390   1412 use Moose;
  390         465  
  390         1734  
7 390     390   1552782 use MooseX::Attribute::FormFuChained;
  390         557  
  390         15994  
8              
9             with 'HTML::FormFu::Role::Render',
10             'HTML::FormFu::Role::FormAndElementMethods',
11             'HTML::FormFu::Role::HasParent',
12             'HTML::FormFu::Role::CustomRoles',
13             'HTML::FormFu::Role::Populate';
14              
15 390         26069 use HTML::FormFu::Attribute qw(
16             mk_attrs
17             mk_attr_accessors
18             mk_output_accessors
19             mk_inherited_accessors
20             mk_inherited_merging_accessors
21 390     390   1453 );
  390         442  
22 390         23099 use HTML::FormFu::ObjectUtil qw(
23             load_config_file
24             load_config_filestem
25             form
26             stash
27             parent
28             get_parent
29 390     390   1642 );
  390         463  
30 390     390   1486 use HTML::FormFu::Util qw( require_class xml_escape process_attrs _merge_hashes );
  390         505  
  390         17314  
31 390     390   1432 use Clone ();
  390         470  
  390         6221  
32 390     390   1252 use Scalar::Util qw( weaken );
  390         461  
  390         14591  
33 390     390   1425 use Carp qw( croak );
  390         484  
  390         29069  
34              
35             use overload (
36             'eq' => '_string_equals',
37             '==' => '_object_equals',
38 375     375   49874 '""' => sub { return shift->render },
39 299     299   1180 bool => sub {1},
40 390         3538 fallback => 1
41 390     390   1554 );
  390         445  
42              
43             __PACKAGE__->mk_attr_accessors(qw( id ));
44              
45             has type => ( is => 'rw', traits => ['FormFuChained'] );
46             has filename => ( is => 'rw', traits => ['FormFuChained'] );
47             has is_field => ( is => 'rw', traits => ['FormFuChained'] );
48             has is_block => ( is => 'rw', traits => ['FormFuChained'] );
49             has is_repeatable => ( is => 'rw', traits => ['FormFuChained'] );
50              
51             after BUILD => sub {
52             my ( $self, $args ) = @_;
53              
54             # TODO move to attribute 'default'
55             $self->attributes( {} );
56             $self->stash( {} );
57              
58             return;
59             };
60              
61             sub name {
62 60023     60023 1 46608 my ( $self, $name ) = @_;
63              
64 60023 100       73996 if ( @_ > 1 ) {
65              
66 1256 100       4084 if ( $name =~ /[\.\[\]]/ ) {
67 1         157 croak <<'ERROR_MESSAGE';
68             element names may not contain periods or square brackets
69             see documentation on nested_names() for details
70             ERROR_MESSAGE
71             }
72              
73 1255         2243 $self->{name} = $name;
74              
75 1255         4450 return $self;
76             }
77              
78 58767         139309 return $self->{name};
79             }
80              
81       1466 0   sub setup { }
82              
83 0     0 0 0 sub get_elements { [] }
84              
85       1 0   sub get_element { }
86              
87 754     754 0 2490 sub get_all_elements { [] }
88              
89       0 0   sub get_all_element { }
90              
91 11     11 0 34 sub get_fields { [] }
92              
93       0 0   sub get_field { }
94              
95 0     0 0 0 sub get_deflators { [] }
96              
97 1     1 0 3 sub get_filters { [] }
98              
99 1     1 0 3 sub get_constraints { [] }
100              
101 1     1 0 3 sub get_inflators { [] }
102              
103 1     1 0 3 sub get_validators { [] }
104              
105 1     1 0 3 sub get_transformers { [] }
106              
107 3     3 0 8 sub get_errors { [] }
108              
109       1 0   sub clear_errors { }
110              
111       1250 0   sub pre_process { }
112              
113       1403 0   sub process { }
114              
115       1403 0   sub post_process { }
116              
117       3 1   sub prepare_id { }
118              
119       1628 1   sub prepare_attrs { }
120              
121             sub get_output_processors {
122 0     0 0 0 my $self = shift;
123              
124 0         0 return $self->form->get_output_processors(@_);
125             }
126              
127             sub get_output_processor {
128 0     0 0 0 my $self = shift;
129              
130 0         0 return $self->form->get_output_processor(@_);
131             }
132              
133             sub _match_default_args {
134 254     254   579 my ( $self, $defaults ) = @_;
135              
136 254 100 66     1145 return {} if !$defaults || !%$defaults;
137              
138             # apply any starting with 'Block', 'Field', 'Input' first, each longest first
139 13         39 my @block = sort { length $a <=> length $b } grep { $_ =~ /^Block/ } keys %$defaults;
  0         0  
  34         77  
140 13         26 my @field = sort { length $a <=> length $b } grep { $_ =~ /^Field/ } keys %$defaults;
  0         0  
  34         54  
141 13         28 my @input = sort { length $a <=> length $b } grep { $_ =~ /^Input/ } keys %$defaults;
  3         10  
  34         61  
142              
143 13         24 my %others = map { $_ => 1 } keys %$defaults;
  34         58  
144             map {
145 13         24 delete $others{$_}
  19         24  
146             } @block, @field, @input;
147              
148             # apply remaining keys, longest first
149 13         23 my $arg = {};
150              
151             KEY:
152 13         43 for my $key ( @block, @field, @input, sort { length $a <=> length $b } keys %others ) {
  5         16  
153 34         182 my @type = split qr{\|}, $key;
154 34         44 my $match;
155              
156             TYPE:
157 34         37 for my $type (@type) {
158 37         32 my $not_in;
159             my $is_in;
160 37 100       110 if ( $type =~ s/^-// ) {
    100          
161 3         4 $not_in = 1;
162             }
163             elsif ( $type =~ s/^\+// ) {
164 1         2 $is_in = 1;
165             }
166              
167 37   100     131 my $check_parents = $not_in || $is_in;
168              
169 37 100       99 if ( $self->_match_default_args_type( $type, $check_parents ) ) {
170 17 100       33 if ( $not_in ) {
171 1         3 next KEY;
172             }
173             else {
174 16         13 $match = 1;
175 16         30 next TYPE;
176             }
177             }
178             }
179              
180 33 100       68 if ( $match ) {
181 15         56 $arg = _merge_hashes( $arg, $defaults->{$key} );
182             }
183             }
184              
185 13         44 return $arg;
186             }
187              
188             sub _match_default_args_type {
189 37     37   45 my ( $self, $type, $check_parents ) = @_;
190              
191 37         30 my @target;
192 37 100       51 if ( $check_parents ) {
193 4         6 my $self = $self;
194 4         11 while ( defined ( my $parent = $self->parent ) ) {
195 5 100       31 last if !$parent->isa('HTML::FormFu::Element');
196 1         1 push @target, $parent;
197 1         3 $self = $parent;
198             }
199             }
200             else {
201 33         40 @target = ($self);
202             }
203              
204 37         52 for my $target (@target) {
205             # handle Block default_args
206 34 100 100     117 if ( 'Block' eq $type
207             && $target->isa('HTML::FormFu::Element::Block') )
208             {
209 3         11 return 1;
210             }
211              
212             # handle Field default_args
213 31 100 100     84 if ( 'Field' eq $type
214             && $target->does('HTML::FormFu::Role::Element::Field') )
215             {
216 2         1718 return 1;
217             }
218              
219             # handle Input default_args
220 29 100 100     971 if ( 'Input' eq $type
221             && $target->does('HTML::FormFu::Role::Element::Input') )
222             {
223 5         1287 return 1;
224             }
225              
226             # handle explicit default_args
227 24 100       1879 if ( $type eq $target->type ) {
228 7         21 return 1;
229             }
230             }
231             }
232              
233             sub clone {
234 193     193 1 184 my ($self) = @_;
235              
236 193         3355 my %new = %$self;
237              
238             $new{tt_args} = Clone::clone( $self->{tt_args} )
239 193 50       592 if $self->{tt_args};
240              
241 193         530 $new{attributes} = Clone::clone( $self->attributes );
242 193         690 $new{model_config} = Clone::clone( $self->model_config );
243              
244 193         512 return bless \%new, ref $self;
245             }
246              
247             sub render_data {
248 1236     1236 0 4622 return shift->render_data_non_recursive(@_);
249             }
250              
251             sub render_data_non_recursive {
252 1628     1628 0 1996 my ( $self, $args ) = @_;
253              
254             my %render = (
255             name => xml_escape( $self->name ),
256             attributes => xml_escape( $self->attributes ),
257             type => $self->type,
258             filename => $self->filename,
259             is_field => $self->is_field,
260             stash => $self->stash,
261             parent => $self->parent,
262 0     0   0 form => sub { return shift->{parent}->form },
263 1628 50       3559 object => $self,
264             $args ? %$args : (),
265             );
266              
267 1628         6443 weaken( $render{parent} );
268              
269 1628         5392 $self->prepare_id( \%render );
270              
271 1628         4977 $self->prepare_attrs( \%render );
272              
273 1628         3494 return \%render;
274             }
275              
276             __PACKAGE__->meta->make_immutable;
277              
278             1;
279              
280             __END__
281              
282             =head1 NAME
283              
284             HTML::FormFu::Element - Element Base Class
285              
286             =head1 VERSION
287              
288             version 2.05
289              
290             =head1 SYNOPSIS
291              
292             ---
293             elements:
294             - type: Text
295             name: username
296             constraints:
297             - type: Required
298              
299             - type: Password
300             name: password
301             constraints:
302             - type: Required
303             - type: Equal
304             others: repeat-password
305              
306             - type: Password
307             name: repeat-password
308              
309             - type: Submit
310              
311             =head1 DESCRIPTION
312              
313             Elements are the basic building block of all forms. Elements may be logical
314             form-fields, blocks such as C<div>s and C<fieldset>s, non-blocks such as
315             C<hr>s and other special elements such as tables.
316              
317             For simple, automatic handling of fieldsets see the
318             L<HTML::FormFu/auto_fieldset> setting.
319              
320             See L<HTML::FormFu/deflators> for details of
321             L<Deflators|HTML::FormFu::Deflator>.
322              
323             See L<HTML::FormFu/FORM LOGIC AND VALIDATION> for details of
324             L<Filters|HTML::FormFu::Filter>,
325             L<Constraints|HTML::FormFu::Constraint>,
326             L<Inflators|HTML::FormFu::Inflator>,
327             L<Validators|HTML::FormFu::Validator> and
328             L<Transformers|HTML::FormFu::Transformer>.
329              
330             =head1 METHODS
331              
332             =head2 name
333              
334             For L<field|HTML::FormFu::Role::Element::Field> element, this value is used as
335             the C<name> attribute which the field's value is associated with.
336              
337             For all elements, the L</name> value can be useful for identifying and
338             retrieving specific elements.
339              
340             =head2 is_field
341              
342             Return Value: boolean
343              
344             Returns C<true> or C<false> depending on whether the element is a logical
345             form-field.
346              
347             This is used by L<HTML::FormFu/get_fields>.
348              
349             =head1 BUILDING AN ELEMENT
350              
351             =head2 load_config_file
352              
353             Arguments: $filename
354              
355             Arguments: \@filenames
356              
357             Populate an element using a config file:
358              
359             ---
360             elements:
361             - type: Block
362             load_config_file: 'elements.yml'
363              
364             See L<HTML::FormFu/load_config_file> for further details.
365              
366             =head2 load_config_filestem
367              
368             Arguments: $filestem
369              
370             Arguments: \@filestems
371              
372             Like L</load_config_file>, but you shouldn't include the file extension
373             in the passed string. This allows you to change your config-file type,
374             without having to change the code that loads the files.
375              
376             =head2 config_file_path
377              
378             Arguments: $directory_name
379              
380             L</config_file_path> defines where configuration files will be
381             searched for, if an absolute path is not given to
382             L</load_config_file>.
383              
384             Default Value: not defined
385              
386             This method is a special 'inherited accessor', which means it can be set on
387             the form, a block element or a single element. When the value is read, if
388             no value is defined it automatically traverses the element's hierarchy of
389             parents, through any block elements and up to the form, searching for a
390             defined value.
391              
392             =head2 config_callback
393              
394             See L<HTML::FormFu/config_callback> for details.
395              
396             =head2 populate
397              
398             See L<HTML::FormFu/populate> for details.
399              
400             =head2 stash
401              
402             See L<HTML::FormFu/stash> for details.
403              
404             =head2 type
405              
406             Returns the C<type> argument originally used to create the element.
407              
408             =head1 CHANGING DEFAULT BEHAVIOUR
409              
410             =head2 render_processed_value
411              
412             See L<HTML::FormFu/render_processed_value> for details.
413              
414             =head2 force_errors
415              
416             See L<HTML::FormFu/force_errors> for details.
417              
418             =head1 ELEMENT ATTRIBUTES
419              
420             See specific element types for which tag attributes are added to.
421              
422             =head2 attributes
423              
424             =head2 attrs
425              
426             Arguments: [%attributes]
427              
428             Arguments: [\%attributes]
429              
430             Return Value: $form
431              
432             See L<HTML::FormFu/attributes> for details.
433              
434             L</attrs> is an alias for L</attributes>.
435              
436             =head2 attributes_xml
437              
438             =head2 attrs_xml
439              
440             See L<HTML::FormFu/attributes_xml> for details.
441              
442             L</attrs_xml> is an alias for L</attributes_xml>.
443              
444             =head2 add_attributes
445              
446             =head2 add_attrs
447              
448             Arguments: [%attributes]
449              
450             Arguments: [\%attributes]
451              
452             Return Value: $form
453              
454             See L<HTML::FormFu/add_attributes> for details.
455              
456             L</add_attrs> is an alias for L</add_attributes>.
457              
458             =head2 add_attributes_xml
459              
460             =head2 add_attrs_xml
461              
462             See L<HTML::FormFu/add_attributes_xml> for details.
463              
464             L</add_attrs_xml> is an alias for L</add_attributes_xml>.
465              
466             =head2 del_attributes
467              
468             =head2 del_attrs
469              
470             Arguments: [%attributes]
471              
472             Arguments: [\%attributes]
473              
474             Return Value: $form
475              
476             See L<HTML::FormFu/del_attributes> for details.
477              
478             L</del_attrs> is an alias for L</del_attributes>.
479              
480             =head2 del_attributes_xml
481              
482             =head2 del_attrs_xml
483              
484             See L<HTML::FormFu/del_attributes_xml> for details.
485              
486             L</del_attrs_xml> is an alias for L</del_attributes_xml>.
487              
488             The following methods are shortcuts for accessing L</attributes> keys.
489              
490             =head2 id
491              
492             Arguments: [$id]
493              
494             Return Value: $id
495              
496             Get or set the element's DOM id.
497              
498             Default Value: none
499              
500             =head1 MODEL / DATABASE INTERACTION
501              
502             See L<HTML::FormFu::Model> for further details and available models.
503              
504             =head2 model_config
505              
506             Arguments: \%config
507              
508             =head1 RENDERING
509              
510             =head2 filename
511              
512             This value identifies which template file should be used by
513             L</render> to render the element.
514              
515             =head2 prepare_id
516              
517             Arguments: $render
518              
519             See L<HTML::FormFu::Role::Element::Field/prepare_id> for details.
520              
521             =head2 prepare_attrs
522              
523             Arguments: $render
524              
525             See L<HTML::FormFu::Role::Element::Field/prepare_attrs> for details.
526              
527             =head2 render
528              
529             Return Value: $string
530              
531             =head1 INTROSPECTION
532              
533             =head2 parent
534              
535             Returns the L<block element|HTML::FormFu::Element::Block> or
536             L<form|HTML::FormFu> object that this element is attached to.
537              
538             =head2 get_parent
539              
540             Arguments: \%options
541              
542             my $repeatable = $field->get_parent({ type => 'Repeatable' });
543              
544             Traverses the parent hierarchy, returning the first parent that matches the
545             supplied options.
546              
547             =head2 form
548              
549             Returns the L<HTML::FormFu> object that the constraint's field is attached
550             to.
551              
552             =head2 clone
553              
554             See L<HTML::FormFu/clone> for details.
555              
556             =head1 ADVANCED CUSTOMISATION
557              
558             =head2 tt_args
559              
560             See L<HTML::FormFu/tt_args> for details.
561              
562             =head2 render_method
563              
564             See L<HTML::FormFu/render_method> for details.
565              
566             =head1 CORE FORM FIELDS
567              
568             =over
569              
570             =item L<HTML::FormFu::Element::Button>
571              
572             =item L<HTML::FormFu::Element::Checkbox>
573              
574             =item L<HTML::FormFu::Element::Checkboxgroup>
575              
576             =item L<HTML::FormFu::Element::ComboBox>
577              
578             =item L<HTML::FormFu::Element::ContentButton>
579              
580             =item L<HTML::FormFu::Element::Date>
581              
582             =item L<HTML::FormFu::Element::Email>
583              
584             =item L<HTML::FormFu::Element::File>
585              
586             =item L<HTML::FormFu::Element::Hidden>
587              
588             =item L<HTML::FormFu::Element::Image>
589              
590             =item L<HTML::FormFu::Element::Number>
591              
592             =item L<HTML::FormFu::Element::Password>
593              
594             =item L<HTML::FormFu::Element::Radio>
595              
596             =item L<HTML::FormFu::Element::Radiogroup>
597              
598             =item L<HTML::FormFu::Element::Reset>
599              
600             =item L<HTML::FormFu::Element::Select>
601              
602             =item L<HTML::FormFu::Element::Submit>
603              
604             =item L<HTML::FormFu::Element::Textarea>
605              
606             =item L<HTML::FormFu::Element::Text>
607              
608             =item L<HTML::FormFu::Element::URL>
609              
610             =back
611              
612             =head1 OTHER CORE ELEMENTS
613              
614             =over
615              
616             =item L<HTML::FormFu::Element::Blank>
617              
618             =item L<HTML::FormFu::Element::Block>
619              
620             =item L<HTML::FormFu::Element::Fieldset>
621              
622             =item L<HTML::FormFu::Element::Hr>
623              
624             =item L<HTML::FormFu::Element::Label>
625              
626             =item L<HTML::FormFu::Element::Multi>
627              
628             =item L<HTML::FormFu::Element::Repeatable>
629              
630             =item L<HTML::FormFu::Element::SimpleTable>
631              
632             =item L<HTML::FormFu::Element::Src>
633              
634             =back
635              
636             =head1 ELEMENT BASE CLASSES
637              
638             The following are base classes for other elements, and generally needn't be
639             used directly.
640              
641             =over
642              
643             =item L<HTML::FormFu::Role::Element::Field>
644              
645             =item L<HTML::FormFu::Role::Element::Group>
646              
647             =item L<HTML::FormFu::Role::Element::Input>
648              
649             =item L<HTML::FormFu::Element::_MultiElement>
650              
651             =item L<HTML::FormFu::Element::_MultiSelect>
652              
653             =item L<HTML::FormFu::Element::_MultiText>
654              
655             =item L<HTML::FormFu::Role::Element::NonBlock>
656              
657             =back
658              
659             =head1 REMOVED METHODS
660              
661             =head2 db
662              
663             Has been removed; use L</default_args> instead.
664              
665             =head1 AUTHOR
666              
667             Carl Franks, C<cfranks@cpan.org>
668              
669             =head1 LICENSE
670              
671             This library is free software, you can redistribute it and/or modify it under
672             the same terms as Perl itself.
673              
674             =cut