File Coverage

blib/lib/HTML/FormHandler/Traits.pm
Criterion Covered Total %
statement 52 57 91.2
branch 10 18 55.5
condition 1 2 50.0
subroutine 10 10 100.0
pod 0 5 0.0
total 73 92 79.3


line stmt bran cond sub pod time code
1             package HTML::FormHandler::Traits;
2             # ABSTRACT: customized replacement for MooseX::Traits
3             $HTML::FormHandler::Traits::VERSION = '0.40067';
4 144     144   92430 use Moose::Role;
  144         217  
  144         1146  
5 144     144   513264 use Class::Load qw/ load_class /;
  144         209  
  144         7978  
6 144     144   1021 use namespace::autoclean;
  144         6197  
  144         1221  
7              
8             has '_trait_namespace' => (
9             init_arg => undef,
10             isa => 'Str',
11             is => 'bare',
12             );
13              
14             my %COMPOSED_CLASS_INDEX;
15             # {
16             # 'HTML::FormHandler::Field::Text' => { 'Role|Another::Role' => 1 },
17             # 'HTML::FormHandler::Field::Select' => { 'My::Role' => 2,
18             # 'My::Role|Your::Role' => 3 },
19             # }
20             my %COMPOSED_META;
21             my $composed_index = 0;
22              
23             sub resolve_traits {
24 1663     1663 0 3260 my ( $class, @traits ) = @_;
25              
26             return map {
27 1663         3187 my $orig = $_;
  2771         3262  
28 2771 50       4911 if ( !ref $orig ) {
29 2771         4805 my $transformed = transform_trait( $class, $orig );
30 2771         8983 load_class($transformed);
31 2771         55349 $transformed;
32             }
33             else {
34 0         0 $orig;
35             }
36             } @traits;
37             }
38              
39             sub transform_trait {
40 2771     2771 0 3322 my ( $class, $name ) = @_;
41 2771 50       6346 return $1 if $name =~ /^[+](.+)$/;
42              
43 2771         8796 my $namespace = $class->meta->find_attribute_by_name('_trait_namespace');
44 2771         151648 my $base;
45 2771 50       8213 if ( $namespace->has_default ) {
46 0         0 $base = $namespace->default;
47 0 0       0 if ( ref $base eq 'CODE' ) {
48 0         0 $base = $base->();
49             }
50             }
51              
52 2771 50       13714 return $name unless $base;
53 0         0 return join '::', $base, $name;
54             }
55              
56             sub composed_class_name {
57 1663     1663 0 5055 my (%options) = @_;
58              
59 1663         2744 my $class = $options{class};
60 1663         5660 my $cache_key = _anon_cache_key( $options{roles} );
61              
62 1663         5878 my $index = $COMPOSED_CLASS_INDEX{$class}{$cache_key};
63 1663 100       4444 if ( defined $index ) {
64 1065         3250 return "${class}::$index";
65             }
66 598         998 $index = ++$composed_index;
67 598         3405 $COMPOSED_CLASS_INDEX{$class}{$cache_key} = $index;
68 598         2353 return "${class}::$index";
69             }
70              
71             sub _anon_cache_key {
72             # Makes something like Role|Role::1
73 1663 50   1663   3852 return join( '|', @{ $_[0] || [] } );
  1663         6849  
74             }
75              
76             sub with_traits {
77 1663     1663 0 17417 my ( $class, @traits ) = @_;
78              
79 1663         4747 @traits = resolve_traits( $class, @traits );
80 1663 50       4202 return $class->meta unless ( scalar @traits );
81              
82 1663         4684 my $class_name = $class->meta->name;
83 1663         20861 my $new_class_name = composed_class_name( class => $class_name, roles => \@traits, );
84 1663         2032 my $meta;
85 1663 100       4654 if ( $meta = $COMPOSED_META{$new_class_name} ) {
86 1065         4415 return $meta->name;
87             }
88             else {
89 598         1841 $meta = $class->meta->create(
90             $new_class_name,
91             superclasses => [$class_name],
92             roles => \@traits,
93             );
94 598         4283624 $COMPOSED_META{$new_class_name} = $meta;
95 598         3997 return $meta->name;
96             }
97             }
98              
99             sub new_with_traits {
100 9     9 0 1336 my ( $class, %args ) = @_;
101              
102 9   50     44 my $traits = delete $args{traits} || [];
103 9         40 my $new_class = $class->with_traits(@$traits);
104 9         41 my $constructor = $new_class->meta->constructor_name;
105 9         428 return $new_class->$constructor(%args);
106             }
107              
108              
109 144     144   79550 no Moose::Role;
  144         226  
  144         687  
110             1;
111              
112             __END__
113              
114             =pod
115              
116             =encoding UTF-8
117              
118             =head1 NAME
119              
120             HTML::FormHandler::Traits - customized replacement for MooseX::Traits
121              
122             =head1 VERSION
123              
124             version 0.40067
125              
126             =head1 SYNOPSIS
127              
128             Use to get a new composed class with traits:
129              
130             my $class = My::Form->with_traits( 'My::Trait', 'Another::Trait' );
131             my $form = $class->new;
132              
133             =head1 AUTHOR
134              
135             FormHandler Contributors - see HTML::FormHandler
136              
137             =head1 COPYRIGHT AND LICENSE
138              
139             This software is copyright (c) 2016 by Gerda Shank.
140              
141             This is free software; you can redistribute it and/or modify it under
142             the same terms as the Perl 5 programming language system itself.
143              
144             =cut