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 161 327 49.2
pod 0 8 0.0
total 376 623 60.3


line stmt bran cond sub pod time code
1 405     405   2902 use strict;
  405         877  
  405         20965  
2              
3             package HTML::FormFu::Attribute;
4             $HTML::FormFu::Attribute::VERSION = '2.07';
5             # ABSTRACT: accessor class
6              
7 405     405   2395 use warnings;
  405         852  
  405         16045  
8              
9 405     405   2706 use Exporter qw( import );
  405         892  
  405         15254  
10 405     405   2525 use Carp qw( croak );
  405         953  
  405         19881  
11 405     405   2836 use Class::MOP::Method;
  405         1041  
  405         16046  
12 405         1209949 use HTML::FormFu::Util qw(
13             append_xml_attribute remove_xml_attribute literal
14 405     405   172281 _parse_args );
  405         1435  
15              
16             our @EXPORT_OK = qw(
17             mk_attrs mk_attr_accessors
18             mk_attr_modifiers mk_inherited_accessors
19             mk_output_accessors mk_inherited_merging_accessors
20             mk_attr_bool_accessors
21             );
22              
23             sub mk_attrs {
24 1324     1324 0 7039 my ( $self, @names ) = @_;
25              
26 1324   33     11303 my $class = ref $self || $self;
27              
28 1324         4618 for my $name (@names) {
29             my $sub = sub {
30 22484     22484   46003 my ( $self, $attrs ) = @_;
        22484      
        22484      
        22389      
        22389      
        6419      
        22389      
        22389      
        3879      
        22389      
        7978      
        3879      
        6419      
        3879      
        6419      
31              
32 22484 100       61422 if ( !exists $self->{$name} ) {
33 8136         18448 $self->{$name} = {};
34             }
35              
36 22484 100       71516 return $self->{$name} if @_ == 1;
37              
38 11800         20004 my $attr_slot = $self->{$name};
39              
40 11800         35411 while ( my ( $key, $value ) = each %$attrs ) {
41 363         1089 $attr_slot->{$key} = $value;
42             }
43              
44 11800         22156 return $self;
45 2924         120479 };
46              
47 2924         14702 my $method = Class::MOP::Method->wrap(
48             body => $sub,
49             name => $name,
50             package_name => $class,
51             );
52              
53             my $xml_sub = sub {
54 2     2   5 my ( $self, $attrs ) = @_;
        2      
        2      
        2      
        2      
        0      
        2      
        2      
        0      
        2      
        0      
        0      
        0      
        0      
        0      
55              
56             return $self->$name(
57 2         8 { map { $_, literal( $attrs->{$_} ) }
  2         5  
58             keys %$attrs
59             } );
60 2924         105296 };
61              
62 2924         13846 my $xml_method = Class::MOP::Method->wrap(
63             body => $xml_sub,
64             name => "${name}_xml",
65             package_name => $class,
66             );
67              
68 2924         81633 $class->meta->add_method( $name, $method );
69 2924         285462 $class->meta->add_method( "${name}_xml", $xml_method );
70              
71             my $loc_sub = sub {
72 0     0   0 my ( $self, $mess, @args ) = @_;
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
73              
74 0 0       0 if ( ref $mess eq 'ARRAY' ) {
75 0         0 ( $mess, @args ) = ( @$mess, @args );
76             }
77              
78 0         0 return $self->$name(
79             literal( $self->form->localize( $mess, @args ) ) );
80 2924         216022 };
81              
82 2924         14002 my $loc_method = Class::MOP::Method->wrap(
83             body => $loc_sub,
84             name => "${name}_loc",
85             package_name => $class,
86             );
87              
88             # add shortcuts
89 2924         85554 my $short = $name;
90 2924 100       20808 if ( $short =~ s/attributes$/attrs/ ) {
91              
92 2828         9617 my $method = Class::MOP::Method->wrap(
93             body => $sub,
94             name => $short,
95             package_name => $class,
96             );
97              
98 2828         78613 my $xml_method = Class::MOP::Method->wrap(
99             body => $xml_sub,
100             name => "${short}_xml",
101             package_name => $class,
102             );
103              
104 2828         74301 my $loc_method = Class::MOP::Method->wrap(
105             body => $loc_sub,
106             name => "${short}_loc",
107             package_name => $class,
108             );
109              
110 2828         71748 $class->meta->add_method( $short, $method );
111 2828         189720 $class->meta->add_method( "${short}_xml", $xml_method );
112 2828         174331 $class->meta->add_method( "${short}_loc", $loc_method );
113             }
114             }
115              
116 1324         92827 mk_add_attrs( $class, @names );
117 1324         6526 mk_del_attrs( $class, @names );
118              
119 1324         4133 return;
120             }
121              
122             sub mk_attr_accessors {
123 1584     1584 0 8057 my ( $self, @names ) = @_;
124              
125 1584   33     12348 my $class = ref $self || $self;
126              
127 1584         5407 for my $name (@names) {
128             my $sub = sub {
129 1948     1948   5144 my ( $self, $attr ) = @_;
        1948      
        1717      
        1725      
        77      
        1717      
        85      
        1948      
        38      
        1948      
        1920      
        1725      
        77      
        1948      
        309      
        1717      
        1725      
        77      
        85      
        1808      
        218      
        38      
        1948      
        38      
130              
131 1948 100       8271 return $self->attributes->{$name} if @_ == 1;
132              
133 957         3537 $self->attributes->{$name} = $attr;
134              
135 957         3014 return $self;
136 4820         234128 };
137              
138 4820         18868 my $method = Class::MOP::Method->wrap(
139             body => $sub,
140             name => $name,
141             package_name => $class,
142             );
143              
144             my $xml_sub = sub {
145 1     1   9 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      
146              
147 1         6 return $self->attributes->{$name} = literal $value;
148 4820         157357 };
149              
150 4820         20155 my $xml_method = Class::MOP::Method->wrap(
151             body => $xml_sub,
152             name => "${name}_xml",
153             package_name => $class,
154             );
155              
156             my $loc_sub = sub {
157 1     1   5 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      
158              
159 1 50       5 if ( ref $mess eq 'ARRAY' ) {
160 0         0 ( $mess, @args ) = ( @$mess, @args );
161             }
162              
163 1         7 return $self->attributes->{$name}
164             = literal( $self->form->localize( $mess, @args ) );
165 4820         132142 };
166              
167 4820         18383 my $loc_method = Class::MOP::Method->wrap(
168             body => $loc_sub,
169             name => "${name}_loc",
170             package_name => $class,
171             );
172              
173 4820         125691 $class->meta->add_method( $name, $method );
174 4820         470115 $class->meta->add_method( "${name}_xml", $xml_method );
175 4820         331614 $class->meta->add_method( "${name}_loc", $loc_method );
176             }
177              
178 1584         112093 return;
179             }
180              
181             sub mk_add_attrs {
182 1324     1324 0 5229 my ( $self, @names ) = @_;
183              
184 1324   33     8072 my $class = ref $self || $self;
185              
186 1324         4072 for my $name (@names) {
187             my $sub = sub {
188 6     6   104 my ( $self, $attrs ) = @_;
        6      
        6      
        6      
        6      
        0      
        6      
        6      
        0      
        6      
        1      
        0      
        0      
        0      
        0      
189              
190 6         32 while ( my ( $key, $value ) = each %$attrs ) {
191 6         28 append_xml_attribute( $self->{$name}, $key, $value );
192             }
193 6         33 return $self;
194 2924         106210 };
195              
196 2924         13555 my $method = Class::MOP::Method->wrap(
197             body => $sub,
198             name => "add_$name",
199             package_name => $class,
200             );
201              
202             my $xml_sub = sub {
203 1     1   3 my ( $self, $attrs ) = @_;
        1      
        1      
        1      
        1      
        0      
        1      
        1      
        0      
        1      
        0      
        0      
        0      
        0      
        0      
204              
205 1         4 my $method = "add_$name";
206              
207             return $self->$method(
208 1         4 { map { $_, literal( $attrs->{$_} ) }
  1         13  
209             keys %$attrs
210             } );
211 2924         93311 };
212              
213 2924         13569 my $xml_method = Class::MOP::Method->wrap(
214             body => $xml_sub,
215             name => "add_${name}_xml",
216             package_name => $class,
217             );
218              
219             my $loc_sub = sub {
220 0     0   0 my ( $self, $mess, @args ) = @_;
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
221              
222 0 0       0 if ( ref $mess eq 'ARRAY' ) {
223 0         0 ( $mess, @args ) = ( @$mess, @args );
224             }
225              
226 0         0 return $self->$method(
227             literal( $self->form->localize( $mess, @args ) ) );
228 2924         85580 };
229              
230 2924         13595 my $loc_method = Class::MOP::Method->wrap(
231             body => $loc_sub,
232             name => "add_${name}_loc",
233             package_name => $class,
234             );
235              
236 2924         80376 $class->meta->add_method( "add_$name", $method );
237 2924         214115 $class->meta->add_method( "add_${name}_xml", $xml_method );
238 2924         201484 $class->meta->add_method( "add_${name}_loc", $loc_method );
239              
240             # add shortcuts
241 2924         191754 my $short = $name;
242 2924 100       16944 if ( $short =~ s/attributes$/attrs/ ) {
243              
244 2828         12505 my $method = Class::MOP::Method->wrap(
245             body => $sub,
246             name => "add_$short",
247             package_name => $class,
248             );
249              
250 2828         90655 my $xml_method = Class::MOP::Method->wrap(
251             body => $xml_sub,
252             name => "add_${short}_xml",
253             package_name => $class,
254             );
255              
256 2828         77371 my $loc_method = Class::MOP::Method->wrap(
257             body => $loc_sub,
258             name => "add_${short}_loc",
259             package_name => $class,
260             );
261              
262 2828         73777 $class->meta->add_method( "add_$short", $method );
263 2828         185331 $class->meta->add_method( "add_${short}_xml", $xml_method );
264 2828         176297 $class->meta->add_method( "add_${short}_loc", $loc_method );
265             }
266             }
267              
268 1324         81128 return;
269             }
270              
271             sub mk_del_attrs {
272 1324     1324 0 5036 my ( $self, @names ) = @_;
273              
274 1324   33     8353 my $class = ref $self || $self;
275              
276 1324         4313 for my $name (@names) {
277             my $sub = sub {
278 0     0   0 my ( $self, $attrs ) = @_;
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
279              
280 0         0 while ( my ( $key, $value ) = each %$attrs ) {
281 0         0 remove_xml_attribute( $self->{$name}, $key, $value );
282             }
283 0         0 return $self;
284 2924         107801 };
285              
286 2924         13888 my $method = Class::MOP::Method->wrap(
287             body => $sub,
288             name => "del_$name",
289             package_name => $class,
290             );
291              
292             my $xml_sub = sub {
293 0     0   0 my ( $self, $attrs ) = @_;
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
294              
295 0         0 my $method = "del_$name";
296              
297             return $self->$method(
298 0         0 { map { $_, literal( $attrs->{$_} ) }
  0         0  
299             keys %$attrs
300             } );
301 2924         94570 };
302              
303 2924         14312 my $xml_method = Class::MOP::Method->wrap(
304             body => $xml_sub,
305             name => "del_${name}_xml",
306             package_name => $class,
307             );
308              
309             my $loc_sub = sub {
310 0     0   0 my ( $self, $mess, @args ) = @_;
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
        0      
311              
312 0 0       0 if ( ref $mess eq 'ARRAY' ) {
313 0         0 ( $mess, @args ) = ( @$mess, @args );
314             }
315              
316 0         0 return $self->$method(
317             literal( $self->form->localize( $mess, @args ) ) );
318 2924         89501 };
319              
320 2924         13800 my $loc_method = Class::MOP::Method->wrap(
321             body => $loc_sub,
322             name => "del_${name}_loc",
323             package_name => $class,
324             );
325              
326 2924         81504 $class->meta->add_method( "del_$name", $method );
327 2924         221447 $class->meta->add_method( "del_${name}_xml", $xml_method );
328 2924         199172 $class->meta->add_method( "del_${name}_loc", $loc_method );
329              
330             # add shortcuts
331 2924         191483 my $short = $name;
332 2924 100       17408 if ( $short =~ s/attributes$/attrs/ ) {
333              
334 2828         12789 my $method = Class::MOP::Method->wrap(
335             body => $sub,
336             name => "del_$short",
337             package_name => $class,
338             );
339              
340 2828         90397 my $xml_method = Class::MOP::Method->wrap(
341             body => $xml_sub,
342             name => "del_${short}_xml",
343             package_name => $class,
344             );
345              
346 2828         78369 my $loc_method = Class::MOP::Method->wrap(
347             body => $loc_sub,
348             name => "del_${short}_loc",
349             package_name => $class,
350             );
351              
352 2828         74843 $class->meta->add_method( "del_$short", $method );
353 2828         186165 $class->meta->add_method( "del_${short}_xml", $xml_method );
354 2828         176752 $class->meta->add_method( "del_${short}_loc", $loc_method );
355             }
356             }
357              
358 1324         78861 return;
359             }
360              
361             sub mk_inherited_accessors {
362 1641     1641 0 6463 my ( $self, @names ) = @_;
363              
364 1641   33     8520 my $class = ref $self || $self;
365              
366 1641         4414 for my $name (@names) {
367             my $sub = sub {
368 17673     17673   36753 my ( $self, $value ) = @_;
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        17673      
        2464      
        21      
        17673      
        17673      
        17673      
        17673      
369              
370 17673 100       38102 if ( @_ > 1 ) {
371 2066         13041 $self->{$name} = $value;
372 2066         5566 return $self;
373             }
374              
375             # micro optimization! this method's called a lot, so access
376             # parent hashkey directly, instead of calling parent()
377 15607   100     62379 while ( defined( my $parent = $self->{parent} )
378             && !defined $self->{$name} )
379             {
380 29703         82101 $self = $parent;
381             }
382 15607         86842 return $self->{$name};
383 12145         732751 };
384              
385             my $no_inherit_sub = sub {
386 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      
        0      
387              
388 0 0       0 if ( @_ > 1 ) {
389 0         0 croak "Cannot call ${name}_no_inherit as a setter";
390             }
391              
392 0         0 return $self->{$name};
393 12145         48488 };
394              
395 12145         39313 my $method = Class::MOP::Method->wrap(
396             body => $sub,
397             name => $name,
398             package_name => $class,
399             );
400              
401 12145         376583 my $no_inherit_method = Class::MOP::Method->wrap(
402             body => $no_inherit_sub,
403             name => "${name}_no_inherit",
404             package_name => $class,
405             );
406              
407 12145         309394 $class->meta->add_method( $name, $method );
408 12145         864607 $class->meta->add_method( "${name}_no_inherit", $no_inherit_method );
409             }
410              
411 1641         116105 return;
412             }
413              
414             sub mk_inherited_merging_accessors {
415 404     404 0 1575 my ( $self, @names ) = @_;
416              
417 404   33     5123 my $class = ref $self || $self;
418              
419 404         2224 $class->mk_inherited_accessors(@names);
420              
421 404         1321 for my $name (@names) {
422             my $sub = sub {
423 1     1   9 my ( $self, $attrs ) = @_;
        1      
        1      
424              
425 1 50       8 if (@_) {
426 1         6 while ( my ( $key, $value ) = each %$attrs ) {
427 1         9 append_xml_attribute( $self->{$name}, $key, $value );
428             }
429 1         4 return $self;
430             }
431              
432             # micro optimization! this method's called a lot, so access
433             # parent hashkey directly, instead of calling parent()
434 0   0     0 while ( defined( my $parent = $self->{parent} )
435             && !defined $self->{$name} )
436             {
437 0         0 $self = $parent;
438             }
439 0         0 return $self->{$name};
440 808         33188 };
441              
442 808         14837 my $method = Class::MOP::Method->wrap(
443             body => $sub,
444             name => "add_$name",
445             package_name => $class,
446             );
447              
448 808         26754 $class->meta->add_method( "add_$name", $method );
449             }
450              
451 404         27775 return;
452             }
453              
454             sub mk_output_accessors {
455 1561     1561 0 7291 my ( $self, @names ) = @_;
456              
457 1561   33     12774 my $class = ref $self || $self;
458              
459 1561         5178 for my $name (@names) {
460             my $sub = sub {
461 8449     8449   28560 my ( $self, $value ) = @_;
        8431      
        5544      
        0      
        2057      
        787      
        3802      
        8449      
        8431      
        2898      
        8449      
        9      
        8431      
462 8449 100       18749 if ( @_ > 1 ) {
463 780         2165 $self->{$name} = $value;
464 780         4628 return $self;
465             }
466 7669         21795 return $self->{$name};
467 2329         62491 };
468              
469 2329         11797 my $method = Class::MOP::Method->wrap(
470             body => $sub,
471             name => $name,
472             package_name => $class,
473             );
474              
475             my $xml_sub = sub {
476 6     6   26 my ( $self, $arg ) = @_;
        5      
        2      
        0      
        0      
        0      
        0      
        6      
        5      
        1      
        6      
        0      
        5      
477              
478 6         26 return $self->$name( literal($arg) );
479 2329         89261 };
480              
481 2329         11756 my $xml_method = Class::MOP::Method->wrap(
482             body => $xml_sub,
483             name => "${name}_xml",
484             package_name => $class,
485             );
486              
487             my $loc_sub = sub {
488 13     13   53 my ( $self, $mess, @args ) = @_;
        13      
        0      
        0      
        0      
        0      
        1      
        13      
        13      
        0      
        13      
        0      
        13      
489              
490 13 100       52 if ( ref $mess eq 'ARRAY' ) {
491 1         5 ( $mess, @args ) = ( @$mess, @args );
492             }
493              
494 13         72 return $self->$name(
495             literal( $self->form->localize( $mess, @args ) ) );
496 2329         67974 };
497              
498 2329         10842 my $loc_method = Class::MOP::Method->wrap(
499             body => $loc_sub,
500             name => "${name}_loc",
501             package_name => $class,
502             );
503              
504 2329         64356 $class->meta->add_method( $name, $method );
505 2329         212034 $class->meta->add_method( "${name}_xml", $xml_method );
506 2329         159278 $class->meta->add_method( "${name}_loc", $loc_method );
507             }
508              
509 1561         105098 return;
510             }
511              
512             sub mk_attr_bool_accessors {
513 323     323 0 1605 my ( $self, @names ) = @_;
514              
515 323   33     3286 my $class = ref $self || $self;
516              
517 323         1414 for my $name (@names) {
518             my $sub = sub {
519 0     0   0 my ( $self, $attr ) = @_;
        0      
        0      
        0      
520              
521 0 0       0 if ( @_ == 1 ) {
522              
523             # Getter
524             return undef ## no critic (ProhibitExplicitReturnUndef);
525 0 0       0 if !exists $self->attributes->{$name};
526              
527             return $self->attributes->{$name}
528 0 0       0 ? $self->attributes->{$name}
529             : undef;
530             }
531              
532             # Any true value sets a bool attribute, e.g.
533             # required="required"
534             # Any false value deletes the attribute
535              
536 0 0       0 if ($attr) {
537 0         0 $self->attributes->{$name} = $name;
538             }
539             else {
540 0         0 delete $self->attributes->{$name};
541             }
542              
543 0         0 return $self;
544 969         50918 };
545              
546 969         4114 my $method = Class::MOP::Method->wrap(
547             body => $sub,
548             name => $name,
549             package_name => $class,
550             );
551              
552 969         29639 $class->meta->add_method( $name, $method );
553             }
554              
555 323         22930 return;
556             }
557              
558             1;
559              
560             __END__
561              
562             =pod
563              
564             =encoding UTF-8
565              
566             =head1 NAME
567              
568             HTML::FormFu::Attribute - accessor class
569              
570             =head1 VERSION
571              
572             version 2.07
573              
574             =head1 SYNOPSIS
575              
576             =head1 DESCRIPTION
577              
578             =head1 METHODS
579              
580             =head1 AUTHOR
581              
582             Carl Franks, C<cfranks@cpan.org>
583              
584             Based on the original source code of L<HTML::Widget::Accessor>, by
585             Sebastian Riedel, C<sri@oook.de>.
586              
587             =head1 LICENSE
588              
589             This library is free software, you can redistribute it and/or modify it under
590             the same terms as Perl itself.
591              
592             =head1 AUTHOR
593              
594             Carl Franks <cpan@fireartist.com>
595              
596             =head1 COPYRIGHT AND LICENSE
597              
598             This software is copyright (c) 2018 by Carl Franks.
599              
600             This is free software; you can redistribute it and/or modify it under
601             the same terms as the Perl 5 programming language system itself.
602              
603             =cut