File Coverage

blib/lib/DBIx/QuickORM/Util.pm
Criterion Covered Total %
statement 96 116 82.7
branch 33 52 63.4
condition 16 37 43.2
subroutine 15 16 93.7
pod 1 7 14.2
total 161 228 70.6


line stmt bran cond sub pod time code
1             package DBIx::QuickORM::Util;
2 377     377   3300 use strict;
  377         801  
  377         15549  
3 377     377   1855 use warnings;
  377         635  
  377         28337  
4              
5             our $VERSION = '0.000019';
6              
7 377     377   264974 use Data::Dumper;
  377         4406301  
  377         36399  
8 377     377   3180 use Scalar::Util qw/blessed/;
  377         738  
  377         22015  
9 377     377   2725 use Carp qw/croak confess/;
  377         724  
  377         23560  
10              
11 377     377   212409 use Module::Pluggable sub_name => '_find_mods';
  377         5265174  
  377         3405  
12             BEGIN {
13 377     377   1628 *_find_paths = \&search_path;
14 377     377   57171 no strict 'refs';
  377         845  
  377         26457  
15 377         1249 delete ${\%{__PACKAGE__ . "\::"}}{search_path};
  377         784  
  377         11267  
16             }
17              
18 377     377   257773 use Importer Importer => 'import';
  377         2762021  
  377         3049  
19              
20             our @EXPORT_OK = qw{
21             load_class
22             find_modules
23             merge_hash_of_objs
24             clone_hash_of_objs
25             column_key
26             debug
27             parse_conflate_args
28             };
29              
30 99     99 0 610 sub column_key { return join ', ' => sort @_ }
31              
32             sub load_class {
33 423     423 1 1616 my ($class, $prefix) = @_;
34              
35 423 100       1338 if ($prefix) {
36 71 100 100     2225 $class = "${prefix}::${class}" unless $class =~ s/^\+// or $class =~ m/^$prefix\b/;
37             }
38              
39 423         1057 my $file = $class;
40 423         3051 $file =~ s{::}{/}g;
41 423         1066 $file .= ".pm";
42              
43 423         892 eval { require $file; $class };
  423         152874  
  407         3191  
44             }
45              
46             sub find_modules {
47 2     2 0 7 my (@prefixes) = @_;
48              
49 2         18 __PACKAGE__->_find_paths(new => @prefixes);
50 2         43 return __PACKAGE__->_find_mods();
51             }
52              
53             sub merge_hash_of_objs {
54 9     9 0 29 my ($hash_a, $hash_b, $merge_params) = @_;
55              
56 9   50     26 $hash_a //= {};
57 9   50     43 $hash_b //= {};
58              
59 9         18 my %out;
60             my %seen;
61              
62 9         58 for my $name (keys %$hash_a, keys %$hash_b) {
63 24 100       122 next if $seen{$name}++;
64              
65 18         43 my $a = $hash_a->{$name};
66 18         36 my $b = $hash_b->{$name};
67              
68 18 100 66     98 if ($a && $b) {
69 6         15 my $r = ref($a);
70 6         33 my $bl = blessed($a);
71              
72 6 50       19 if ($bl) { $out{$name} = $a->merge($b, %$merge_params) }
  6 0       37  
    0          
73 0         0 elsif ($r eq 'HASH') { $out{$name} = {%$a, %$b} }
74 0         0 elsif ($r eq 'ARRAY') { $out{$name} = [@$b] } # Second array wins
75 0         0 else { $out{$name} = $b } # Second value wins
76              
77 6         60 next;
78             }
79              
80 12   33     33 my $v = $a // $b;
81 12         29 my $r = ref($v);
82 12         24 my $bl = blessed($v);
83 12 100       51 if ($bl) { $out{$name} = $v->clone(%$merge_params) }
  6 50       27  
    0          
84 6         26 elsif ($r eq 'ARRAY') { $out{$name} = [@$a] }
85 0         0 elsif ($r eq 'HASH') { $out{$name} = clone_hash_of_objs($v, %$merge_params) }
86 0         0 else { $out{$name} = $v }
87             }
88              
89 9         64 return \%out;
90             }
91              
92             sub clone_hash_of_objs {
93 56     56 0 147 my ($hash, $clone_params) = @_;
94              
95 56 50       218 croak "Need a hashref, got '$hash'" unless ref($hash) eq 'HASH';
96              
97 56         144 my %out;
98             my %seen;
99              
100 56         496 for my $name (keys %$hash) {
101 127 50       388 my $val = $hash->{$name} or next;
102 127 100       373 if (blessed($val)) {
103 82         418 $out{$name} = $hash->{$name}->clone(%$clone_params);
104 82         262 next;
105             }
106              
107 45         107 my $r = ref($val);
108 45 50       188 if ($r eq 'ARRAY') {
    0          
109 45         188 $out{$name} = [@$val];
110             }
111             elsif ($r eq 'HASH') {
112 0         0 $out{$name} = clone_hash_of_objs($val, $clone_params);
113             }
114             }
115              
116 56         309 return \%out;
117             }
118              
119              
120             sub debug {
121 0     0 0 0 local $Data::Dumper::Sortkeys = 1;
122 0         0 local $Data::Dumper::Terse = 1;
123 0         0 local $Data::Dumper::Quotekeys = 0;
124 0         0 local $Data::Dumper::Deepcopy = 1;
125 0         0 local $Data::Dumper::Trailingcomma = 1;
126 0         0 my $out = Dumper(@_);
127 0 0       0 return $out if defined wantarray;
128 0         0 print $out;
129             }
130              
131             sub parse_conflate_args {
132 54     54 0 137 my ($proto, %params);
133 54 100       205 $proto = shift if @_ % 2;
134              
135 54 50 66     301 if (!blessed($_[0]) && eval { $_[0]->does('DBIx::QuickORM::Role::Type') ? 1 : 0 }) {
  54 100       1506  
136 15         313 (@params{qw/class value/}) = (shift(@_), shift(@_));
137 15         122 %params = (%params, @_);
138             }
139             else {
140 39         71844 %params = @_;
141             }
142              
143 54 100       275 if ($proto) {
144 39 50       123 if (blessed($proto)) {
145 0   0     0 $params{value} //= $proto;
146             }
147             else {
148 39         98 my $ref = ref($proto);
149 39         78 my $is_class;
150 39 50       150 if ($ref) {
151 0         0 $is_class = 0;
152             }
153             else {
154 39         90 my $file = "$proto.pm";
155 39         297 $file =~ s{::}{/}g;
156 39 100       190 $is_class = $INC{$file} ? 1 : 0;
157             }
158              
159 39 100       102 if ($is_class) {
160 35   33     325 $params{class} //= $proto;
161             }
162             else {
163 4   33     55 $params{value} //= $proto;
164             }
165             }
166             }
167              
168 54 50       214 confess "'value' argument must be present unless called on an instance of a type class" unless exists $params{value};
169              
170 54   33     277 $params{class} //= blessed($params{value}) // caller;
      66        
171              
172 54 100       291 return \%params if $params{affinity};
173              
174 14   50     66 my $source = $params{source} // return \%params;
175 0   0       my $dialect = $params{dialect} // return \%params;
176 0   0       my $field = $params{field} // return \%params;
177 0           $params{affinity} = $source->field_affinity($field, $dialect);
178              
179 0           return \%params;
180             }
181              
182              
183             1;
184              
185             __END__
186              
187             =head1 EXPORTS
188              
189             =over 4
190              
191             =item $class_or_false = load_class($class) or die "Error: $@"
192              
193             Loads the class.
194              
195             On success it returns the class name.
196              
197             On Failure it returns false and the $@ variable is set to the error.
198              
199             =back
200              
201             =cut