File Coverage

blib/lib/HTML/FormFu/Attribute.pm
Criterion Covered Total %
statement 184 220 83.6
branch 20 38 52.6
condition 11 30 36.6
subroutine 160 325 49.2
pod 0 8 0.0
total 375 621 60.3


line stmt bran cond sub pod time code
1             package HTML::FormFu::Attribute;
2              
3 401     401   1433 use strict;
  401         448  
  401         10224  
4 401     401   1324 use warnings;
  401         457  
  401         15802  
5              
6             our $VERSION = '2.05'; # VERSION
7              
8 401     401   1489 use Exporter qw( import );
  401         425  
  401         10382  
9 401     401   1296 use Carp qw( croak );
  401         439  
  401         14425  
10 401     401   1631 use Class::MOP::Method;
  401         498  
  401         11114  
11 401         863569 use HTML::FormFu::Util qw(
12             append_xml_attribute remove_xml_attribute literal
13 401     401   134819 _parse_args );
  401         790  
14              
15             our @EXPORT_OK = qw(
16             mk_attrs mk_attr_accessors
17             mk_attr_modifiers mk_inherited_accessors
18             mk_output_accessors mk_inherited_merging_accessors
19             mk_attr_bool_accessors
20             );
21              
22             sub mk_attrs {
23 1315     1315 0 4609 my ( $self, @names ) = @_;
24              
25 1315   33     10884 my $class = ref $self || $self;
26              
27 1315         4279 for my $name (@names) {
28             my $sub = sub {
29 22485     22485   22841 my ( $self, $attrs ) = @_;
        22485      
        22485      
        22390      
        22390      
        6105      
        22390      
        22390      
        3748      
        22390      
        8156      
        3748      
        6105      
        3748      
        6105      
30              
31 22485 100       44189 if ( !exists $self->{$name} ) {
32 8139         11301 $self->{$name} = {};
33             }
34              
35 22485 100       53049 return $self->{$name} if @_ == 1;
36              
37 11781         11516 my $attr_slot = $self->{$name};
38              
39 11781         25116 while ( my ( $key, $value ) = each %$attrs ) {
40 357         762 $attr_slot->{$key} = $value;
41             }
42              
43 11781         14596 return $self;
44 2911         69144 };
45              
46 2911         11841 my $method = Class::MOP::Method->wrap(
47             body => $sub,
48             name => $name,
49             package_name => $class,
50             );
51              
52             my $xml_sub = sub {
53 2     2   3 my ( $self, $attrs ) = @_;
        2      
        2      
        2      
        2      
        0      
        2      
        2      
        0      
        2      
        0      
        0      
        0      
        0      
        0      
54              
55             return $self->$name( {
56 2         5 map { $_, literal( $attrs->{$_} ) }
  2         5  
57             keys %$attrs
58             } );
59 2911         64823 };
60              
61 2911         11503 my $xml_method = Class::MOP::Method->wrap(
62             body => $xml_sub,
63             name => "${name}_xml",
64             package_name => $class,
65             );
66              
67 2911         45823 $class->meta->add_method( $name, $method );
68 2911         179923 $class->meta->add_method( "${name}_xml", $xml_method );
69              
70             my $loc_sub = sub {
71 0     0   0 my ( $self, $mess, @args ) = @_;
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
72              
73 0 0       0 if ( ref $mess eq 'ARRAY' ) {
74 0         0 ( $mess, @args ) = ( @$mess, @args );
75             }
76              
77 0         0 return $self->$name(
78             literal( $self->form->localize( $mess, @args ) ) );
79 2911         118912 };
80              
81 2911         10116 my $loc_method = Class::MOP::Method->wrap(
82             body => $loc_sub,
83             name => "${name}_loc",
84             package_name => $class,
85             );
86              
87             # add shortcuts
88 2911         48387 my $short = $name;
89 2911 100       15358 if ( $short =~ s/attributes$/attrs/ ) {
90              
91 2815         6999 my $method = Class::MOP::Method->wrap(
92             body => $sub,
93             name => $short,
94             package_name => $class,
95             );
96              
97 2815         45248 my $xml_method = Class::MOP::Method->wrap(
98             body => $xml_sub,
99             name => "${short}_xml",
100             package_name => $class,
101             );
102              
103 2815         41584 my $loc_method = Class::MOP::Method->wrap(
104             body => $loc_sub,
105             name => "${short}_loc",
106             package_name => $class,
107             );
108              
109 2815         39710 $class->meta->add_method( $short, $method );
110 2815         104763 $class->meta->add_method( "${short}_xml", $xml_method );
111 2815         92527 $class->meta->add_method( "${short}_loc", $loc_method );
112             }
113             }
114              
115 1315         53165 mk_add_attrs( $class, @names );
116 1315         4326 mk_del_attrs( $class, @names );
117              
118 1315         2918 return;
119             }
120              
121             sub mk_attr_accessors {
122 1573     1573 0 5036 my ( $self, @names ) = @_;
123              
124 1573   33     10409 my $class = ref $self || $self;
125              
126 1573         3520 for my $name (@names) {
127             my $sub = sub {
128 1942     1942   2961 my ( $self, $attr ) = @_;
        1942      
        1711      
        1719      
        77      
        1711      
        85      
        1942      
        38      
        1942      
        1914      
        1719      
        77      
        1942      
        299      
        1711      
        1719      
        77      
        85      
        1802      
        208      
        38      
        1942      
        38      
129              
130 1942 100       5769 return $self->attributes->{$name} if @_ == 1;
131              
132 958         2647 $self->attributes->{$name} = $attr;
133              
134 958         2582 return $self;
135 4790         126593 };
136              
137 4790         13141 my $method = Class::MOP::Method->wrap(
138             body => $sub,
139             name => $name,
140             package_name => $class,
141             );
142              
143             my $xml_sub = sub {
144 1     1   6 my ( $self, $value ) = @_;
        1      
        0      
        0      
        0      
        0      
        0      
        1      
        0      
        1      
        0      
        0      
        0      
        1      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        1      
        0      
145              
146 1         5 return $self->attributes->{$name} = literal $value;
147 4790         93942 };
148              
149 4790         14889 my $xml_method = Class::MOP::Method->wrap(
150             body => $xml_sub,
151             name => "${name}_xml",
152             package_name => $class,
153             );
154              
155             my $loc_sub = sub {
156 1     1   6 my ( $self, $mess, @args ) = @_;
        1      
        1      
        1      
        0      
        1      
        0      
        1      
        0      
        1      
        1      
        1      
        0      
        1      
        0      
        1      
        1      
        0      
        0      
        1      
        0      
        0      
        1      
        0      
157              
158 1 50       9 if ( ref $mess eq 'ARRAY' ) {
159 0         0 ( $mess, @args ) = ( @$mess, @args );
160             }
161              
162 1         8 return $self->attributes->{$name} =
163             literal( $self->form->localize( $mess, @args ) );
164 4790         73339 };
165              
166 4790         13604 my $loc_method = Class::MOP::Method->wrap(
167             body => $loc_sub,
168             name => "${name}_loc",
169             package_name => $class,
170             );
171              
172 4790         70129 $class->meta->add_method( $name, $method );
173 4790         304480 $class->meta->add_method( "${name}_xml", $xml_method );
174 4790         183478 $class->meta->add_method( "${name}_loc", $loc_method );
175             }
176              
177 1573         60646 return;
178             }
179              
180             sub mk_add_attrs {
181 1315     1315 0 3208 my ( $self, @names ) = @_;
182              
183 1315   33     7248 my $class = ref $self || $self;
184              
185 1315         2820 for my $name (@names) {
186             my $sub = sub {
187 6     6   57 my ( $self, $attrs ) = @_;
        6      
        6      
        6      
        6      
        0      
        6      
        6      
        0      
        6      
        1      
        0      
        0      
        0      
        0      
188              
189 6         27 while ( my ( $key, $value ) = each %$attrs ) {
190 6         28 append_xml_attribute( $self->{$name}, $key, $value );
191             }
192 6         18 return $self;
193 2911         56647 };
194              
195 2911         9928 my $method = Class::MOP::Method->wrap(
196             body => $sub,
197             name => "add_$name",
198             package_name => $class,
199             );
200              
201             my $xml_sub = sub {
202 1     1   2 my ( $self, $attrs ) = @_;
        1      
        1      
        1      
        1      
        0      
        1      
        1      
        0      
        1      
        0      
        0      
        0      
        0      
        0      
203              
204 1         3 my $method = "add_$name";
205              
206             return $self->$method( {
207 1         2 map { $_, literal( $attrs->{$_} ) }
  1         3  
208             keys %$attrs
209             } );
210 2911         53045 };
211              
212 2911         10360 my $xml_method = Class::MOP::Method->wrap(
213             body => $xml_sub,
214             name => "add_${name}_xml",
215             package_name => $class,
216             );
217              
218             my $loc_sub = sub {
219 0     0   0 my ( $self, $mess, @args ) = @_;
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
220              
221 0 0       0 if ( ref $mess eq 'ARRAY' ) {
222 0         0 ( $mess, @args ) = ( @$mess, @args );
223             }
224              
225 0         0 return $self->$method(
226             literal( $self->form->localize( $mess, @args ) ) );
227 2911         47243 };
228              
229 2911         9812 my $loc_method = Class::MOP::Method->wrap(
230             body => $loc_sub,
231             name => "add_${name}_loc",
232             package_name => $class,
233             );
234              
235 2911         43313 $class->meta->add_method( "add_$name", $method );
236 2911         118723 $class->meta->add_method( "add_${name}_xml", $xml_method );
237 2911         108100 $class->meta->add_method( "add_${name}_loc", $loc_method );
238              
239             # add shortcuts
240 2911         103400 my $short = $name;
241 2911 100       12868 if ( $short =~ s/attributes$/attrs/ ) {
242              
243 2815         9422 my $method = Class::MOP::Method->wrap(
244             body => $sub,
245             name => "add_$short",
246             package_name => $class,
247             );
248              
249 2815         51935 my $xml_method = Class::MOP::Method->wrap(
250             body => $xml_sub,
251             name => "add_${short}_xml",
252             package_name => $class,
253             );
254              
255 2815         42141 my $loc_method = Class::MOP::Method->wrap(
256             body => $loc_sub,
257             name => "add_${short}_loc",
258             package_name => $class,
259             );
260              
261 2815         39903 $class->meta->add_method( "add_$short", $method );
262 2815         99589 $class->meta->add_method( "add_${short}_xml", $xml_method );
263 2815         89825 $class->meta->add_method( "add_${short}_loc", $loc_method );
264             }
265             }
266              
267 1315         41328 return;
268             }
269              
270             sub mk_del_attrs {
271 1315     1315 0 2906 my ( $self, @names ) = @_;
272              
273 1315   33     6265 my $class = ref $self || $self;
274              
275 1315         2817 for my $name (@names) {
276             my $sub = sub {
277 0     0   0 my ( $self, $attrs ) = @_;
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
278              
279 0         0 while ( my ( $key, $value ) = each %$attrs ) {
280 0         0 remove_xml_attribute( $self->{$name}, $key, $value );
281             }
282 0         0 return $self;
283 2911         58332 };
284              
285 2911         9704 my $method = Class::MOP::Method->wrap(
286             body => $sub,
287             name => "del_$name",
288             package_name => $class,
289             );
290              
291             my $xml_sub = sub {
292 0     0   0 my ( $self, $attrs ) = @_;
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
293              
294 0         0 my $method = "del_$name";
295              
296             return $self->$method( {
297 0         0 map { $_, literal( $attrs->{$_} ) }
  0         0  
298             keys %$attrs
299             } );
300 2911         52565 };
301              
302 2911         10114 my $xml_method = Class::MOP::Method->wrap(
303             body => $xml_sub,
304             name => "del_${name}_xml",
305             package_name => $class,
306             );
307              
308             my $loc_sub = sub {
309 0     0   0 my ( $self, $mess, @args ) = @_;
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
310              
311 0 0       0 if ( ref $mess eq 'ARRAY' ) {
312 0         0 ( $mess, @args ) = ( @$mess, @args );
313             }
314              
315 0         0 return $self->$method(
316             literal( $self->form->localize( $mess, @args ) ) );
317 2911         46210 };
318              
319 2911         9551 my $loc_method = Class::MOP::Method->wrap(
320             body => $loc_sub,
321             name => "del_${name}_loc",
322             package_name => $class,
323             );
324              
325 2911         43014 $class->meta->add_method( "del_$name", $method );
326 2911         122188 $class->meta->add_method( "del_${name}_xml", $xml_method );
327 2911         107841 $class->meta->add_method( "del_${name}_loc", $loc_method );
328              
329             # add shortcuts
330 2911         101540 my $short = $name;
331 2911 100       12356 if ( $short =~ s/attributes$/attrs/ ) {
332              
333 2815         8685 my $method = Class::MOP::Method->wrap(
334             body => $sub,
335             name => "del_$short",
336             package_name => $class,
337             );
338              
339 2815         51912 my $xml_method = Class::MOP::Method->wrap(
340             body => $xml_sub,
341             name => "del_${short}_xml",
342             package_name => $class,
343             );
344              
345 2815         41966 my $loc_method = Class::MOP::Method->wrap(
346             body => $loc_sub,
347             name => "del_${short}_loc",
348             package_name => $class,
349             );
350              
351 2815         39340 $class->meta->add_method( "del_$short", $method );
352 2815         101634 $class->meta->add_method( "del_${short}_xml", $xml_method );
353 2815         90723 $class->meta->add_method( "del_${short}_loc", $loc_method );
354             }
355             }
356              
357 1315         40943 return;
358             }
359              
360             sub mk_inherited_accessors {
361 1625     1625 0 4079 my ( $self, @names ) = @_;
362              
363 1625   33     7085 my $class = ref $self || $self;
364              
365 1625         2693 for my $name (@names) {
366             my $sub = sub {
367 17505     17505   18775 my ( $self, $value ) = @_;
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        17505      
        2464      
        21      
        17505      
        17505      
        17505      
        17505      
368              
369 17505 100       26980 if ( @_ > 1 ) {
370 2045         10195 $self->{$name} = $value;
371 2045         3959 return $self;
372             }
373              
374             # micro optimization! this method's called a lot, so access
375             # parent hashkey directly, instead of calling parent()
376 15460   100     55009 while ( defined( my $parent = $self->{parent} )
377             && !defined $self->{$name} )
378             {
379 29541         66014 $self = $parent;
380             }
381 15460         70287 return $self->{$name};
382 11625         385418 };
383              
384             my $no_inherit_sub = sub {
385 0     0   0 my ( $self, $value ) = @_;
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
386              
387 0 0       0 if ( @_ > 1 ) {
388 0         0 croak "Cannot call ${name}_no_inherit as a setter";
389             }
390              
391 0         0 return $self->{$name};
392 11625         26206 };
393              
394 11625         24839 my $method = Class::MOP::Method->wrap(
395             body => $sub,
396             name => $name,
397             package_name => $class,
398             );
399              
400 11625         201783 my $no_inherit_method = Class::MOP::Method->wrap(
401             body => $no_inherit_sub,
402             name => "${name}_no_inherit",
403             package_name => $class,
404             );
405              
406 11625         159018 $class->meta->add_method( $name, $method );
407 11625         450827 $class->meta->add_method( "${name}_no_inherit", $no_inherit_method );
408             }
409              
410 1625         63154 return;
411             }
412              
413             sub mk_inherited_merging_accessors {
414 400     400 0 930 my ( $self, @names ) = @_;
415              
416 400   33     2853 my $class = ref $self || $self;
417              
418 400         1197 $class->mk_inherited_accessors(@names);
419              
420 400         845 for my $name (@names) {
421             my $sub = sub {
422 1     1   6 my ( $self, $attrs ) = @_;
        1      
        1      
423              
424 1 50       4 if (@_) {
425 1         4 while ( my ( $key, $value ) = each %$attrs ) {
426 1         7 append_xml_attribute( $self->{$name}, $key, $value );
427             }
428 1         2 return $self;
429             }
430              
431             # micro optimization! this method's called a lot, so access
432             # parent hashkey directly, instead of calling parent()
433 0   0     0 while ( defined( my $parent = $self->{parent} )
434             && !defined $self->{$name} )
435             {
436 0         0 $self = $parent;
437             }
438 0         0 return $self->{$name};
439 800         17564 };
440              
441 800         2868 my $method = Class::MOP::Method->wrap(
442             body => $sub,
443             name => "add_$name",
444             package_name => $class,
445             );
446              
447 800         13768 $class->meta->add_method( "add_$name", $method );
448             }
449              
450 400         15130 return;
451             }
452              
453             sub mk_output_accessors {
454 1550     1550 0 4587 my ( $self, @names ) = @_;
455              
456 1550   33     10679 my $class = ref $self || $self;
457              
458 1550         3605 for my $name (@names) {
459             my $sub = sub {
460 8456     8456   16870 my ( $self, $value ) = @_;
        8438      
        5526      
        0      
        2057      
        787      
        3762      
        8456      
        8438      
        2898      
        8456      
        9      
        8438      
461 8456 100       12840 if ( @_ > 1 ) {
462 774         1254 $self->{$name} = $value;
463 774         3380 return $self;
464             }
465 7682         15871 return $self->{$name};
466 2316         37632 };
467              
468 2316         8972 my $method = Class::MOP::Method->wrap(
469             body => $sub,
470             name => $name,
471             package_name => $class,
472             );
473              
474             my $xml_sub = sub {
475 6     6   13 my ( $self, $arg ) = @_;
        5      
        2      
        0      
        0      
        0      
        0      
        6      
        5      
        1      
        6      
        0      
        5      
476              
477 6         25 return $self->$name( literal($arg) );
478 2316         56174 };
479              
480 2316         9178 my $xml_method = Class::MOP::Method->wrap(
481             body => $xml_sub,
482             name => "${name}_xml",
483             package_name => $class,
484             );
485              
486             my $loc_sub = sub {
487 13     13   35 my ( $self, $mess, @args ) = @_;
        13      
        0      
        0      
        0      
        0      
        1      
        13      
        13      
        0      
        13      
        0      
        13      
488              
489 13 100       38 if ( ref $mess eq 'ARRAY' ) {
490 1         4 ( $mess, @args ) = ( @$mess, @args );
491             }
492              
493 13         85 return $self->$name(
494             literal( $self->form->localize( $mess, @args ) ) );
495 2316         38046 };
496              
497 2316         8172 my $loc_method = Class::MOP::Method->wrap(
498             body => $loc_sub,
499             name => "${name}_loc",
500             package_name => $class,
501             );
502              
503 2316         36409 $class->meta->add_method( $name, $method );
504 2316         132282 $class->meta->add_method( "${name}_xml", $xml_method );
505 2316         90488 $class->meta->add_method( "${name}_loc", $loc_method );
506             }
507              
508 1550         59964 return;
509             }
510              
511             sub mk_attr_bool_accessors {
512 322     322 0 988 my ( $self, @names ) = @_;
513              
514 322   33     2329 my $class = ref $self || $self;
515              
516 322         819 for my $name (@names) {
517             my $sub = sub {
518 0     0   0 my ( $self, $attr ) = @_;
        0      
        0      
        0      
519              
520 0 0       0 if ( @_ == 1 ) {
521             # Getter
522             return undef ## no critic (ProhibitExplicitReturnUndef);
523 0 0       0 if !exists $self->attributes->{$name};
524              
525 0 0       0 return $self->attributes->{$name} ? $self->attributes->{$name}
526             : undef;
527             }
528              
529             # Any true value sets a bool attribute, e.g.
530             # required="required"
531             # Any false value deletes the attribute
532              
533 0 0       0 if ( $attr ) {
534 0         0 $self->attributes->{$name} = $name;
535             }
536             else {
537 0         0 delete $self->attributes->{$name};
538             }
539              
540 0         0 return $self;
541 966         27086 };
542              
543 966         2732 my $method = Class::MOP::Method->wrap(
544             body => $sub,
545             name => $name,
546             package_name => $class,
547             );
548              
549 966         16370 $class->meta->add_method( $name, $method );
550             }
551              
552 322         12289 return;
553             }
554              
555              
556             1;
557              
558             __END__
559              
560             =head1 NAME
561              
562             HTML::FormFu::Attribute - accessor class
563              
564             =head1 VERSION
565              
566             version 2.05
567              
568             =head1 SYNOPSIS
569              
570             =head1 DESCRIPTION
571              
572             =head1 METHODS
573              
574             =head1 AUTHOR
575              
576             Carl Franks, C<cfranks@cpan.org>
577              
578             Based on the original source code of L<HTML::Widget::Accessor>, by
579             Sebastian Riedel, C<sri@oook.de>.
580              
581             =head1 LICENSE
582              
583             This library is free software, you can redistribute it and/or modify it under
584             the same terms as Perl itself.
585              
586             =cut