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.40068';
4 146     146   112021 use Moose::Role;
  146         431  
  146         1364  
5 146     146   782469 use Class::Load qw/ load_class /;
  146         466  
  146         9013  
6 146     146   1479 use namespace::autoclean;
  146         6621  
  146         1433  
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 1674     1674 0 5401 my ( $class, @traits ) = @_;
25              
26             return map {
27 1674         4632 my $orig = $_;
  2788         5873  
28 2788 50       11489 if ( !ref $orig ) {
29 2788         7985 my $transformed = transform_trait( $class, $orig );
30 2788         12028 load_class($transformed);
31 2788         93690 $transformed;
32             }
33             else {
34 0         0 $orig;
35             }
36             } @traits;
37             }
38              
39             sub transform_trait {
40 2788     2788 0 7421 my ( $class, $name ) = @_;
41 2788 50       9859 return $1 if $name =~ /^[+](.+)$/;
42              
43 2788         12558 my $namespace = $class->meta->find_attribute_by_name('_trait_namespace');
44 2788         278041 my $base;
45 2788 50       11811 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 2788 50       20581 return $name unless $base;
53 0         0 return join '::', $base, $name;
54             }
55              
56             sub composed_class_name {
57 1674     1674 0 7904 my (%options) = @_;
58              
59 1674         4546 my $class = $options{class};
60 1674         5674 my $cache_key = _anon_cache_key( $options{roles} );
61              
62 1674         6144 my $index = $COMPOSED_CLASS_INDEX{$class}{$cache_key};
63 1674 100       5739 if ( defined $index ) {
64 1070         4674 return "${class}::$index";
65             }
66 604         1849 $index = ++$composed_index;
67 604         2195 $COMPOSED_CLASS_INDEX{$class}{$cache_key} = $index;
68 604         3099 return "${class}::$index";
69             }
70              
71             sub _anon_cache_key {
72             # Makes something like Role|Role::1
73 1674 50   1674   3645 return join( '|', @{ $_[0] || [] } );
  1674         11092  
74             }
75              
76             sub with_traits {
77 1674     1674 0 26174 my ( $class, @traits ) = @_;
78              
79 1674         8916 @traits = resolve_traits( $class, @traits );
80 1674 50       6528 return $class->meta unless ( scalar @traits );
81              
82 1674         6765 my $class_name = $class->meta->name;
83 1674         35885 my $new_class_name = composed_class_name( class => $class_name, roles => \@traits, );
84 1674         3808 my $meta;
85 1674 100       6948 if ( $meta = $COMPOSED_META{$new_class_name} ) {
86 1070         6050 return $meta->name;
87             }
88             else {
89 604         2720 $meta = $class->meta->create(
90             $new_class_name,
91             superclasses => [$class_name],
92             roles => \@traits,
93             );
94 604         6439210 $COMPOSED_META{$new_class_name} = $meta;
95 604         8196 return $meta->name;
96             }
97             }
98              
99             sub new_with_traits {
100 9     9 0 2054 my ( $class, %args ) = @_;
101              
102 9   50     51 my $traits = delete $args{traits} || [];
103 9         56 my $new_class = $class->with_traits(@$traits);
104 9         65 my $constructor = $new_class->meta->constructor_name;
105 9         695 return $new_class->$constructor(%args);
106             }
107              
108              
109 146     146   90367 no Moose::Role;
  146         379  
  146         931  
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.40068
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) 2017 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