File Coverage

blib/lib/Module/Load/Util.pm
Criterion Covered Total %
statement 61 63 96.8
branch 46 52 88.4
condition 3 5 60.0
subroutine 5 5 100.0
pod 2 2 100.0
total 117 127 92.1


line stmt bran cond sub pod time code
1             package Module::Load::Util;
2              
3 1     1   64391 use strict 'subs', 'vars';
  1         10  
  1         30  
4 1     1   429 use Regexp::Pattern::Perl::Module ();
  1         193  
  1         91  
5              
6             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
7             our $DATE = '2022-02-11'; # DATE
8             our $DIST = 'Module-Load-Util'; # DIST
9             our $VERSION = '0.008'; # VERSION
10              
11 1     1   6 use Exporter 'import';
  1         1  
  1         612  
12             our @EXPORT_OK = qw(
13             load_module_with_optional_args
14             instantiate_class_with_optional_args
15             );
16              
17             sub load_module_with_optional_args {
18 18 100   18 1 28385 my $opts = ref($_[0]) eq 'HASH' ? shift : {};
19 18         32 my $module_with_optional_args = shift;
20              
21             my $target_package =
22             defined $opts->{target_package} ? $opts->{target_package} :
23             defined $opts->{caller} ? $opts->{caller} :
24 18 50       69 caller(0);
    100          
25             # check because we will use eval ""
26             $target_package =~ $Regexp::Pattern::Perl::Module::RE{perl_modname}{pat}
27 18 50       445 or die "Invalid syntax in target package '$target_package'";
28              
29 18         38 my ($module, $args) = @_;
30 18 100       78 if (ref $module_with_optional_args eq 'ARRAY') {
    50          
    100          
31 5 100 66     29 die "array form or module/class name must have 1 or 2 elements"
32             unless @$module_with_optional_args == 1 || @$module_with_optional_args == 2;
33 4         10 $module = $module_with_optional_args->[0];
34 4   50     13 $args = $module_with_optional_args->[1] || [];
35 4 100       13 $args = [%$args] if ref $args eq 'HASH';
36 4 100       17 die "In array form of module/class name, the 2nd element must be ".
37             "arrayref or hashref" unless ref $args eq 'ARRAY';
38             } elsif (ref $module_with_optional_args) {
39 0         0 die "module/class name must be string or 2-element array, not ".
40             $module_with_optional_args;
41             } elsif ($module_with_optional_args =~ /(.+?)=(.*)/) {
42 8         25 $module = $1;
43 8         31 $args = [split /,/, $2];
44             } else {
45 5         9 $module = $module_with_optional_args;
46 5         7 $args = [];
47             }
48              
49 1         3 my @ns_prefixes = $opts->{ns_prefixes} ? @{$opts->{ns_prefixes}} :
50 16 100       62 defined($opts->{ns_prefix}) ? ($opts->{ns_prefix}) : ('');
    100          
51 16 100       32 my $try_all = $opts->{ns_prefixes} ? 1:0;
52 16         20 my $module_with_prefix;
53 16         44 for my $i (0 .. $#ns_prefixes) {
54 17         25 my $ns_prefix = $ns_prefixes[$i];
55 17 100       37 if (length $ns_prefix) {
56 3 50       13 $module_with_prefix =
57             $ns_prefix . ($ns_prefix =~ /::\z/ ? '':'::') . $module;
58             } else {
59 14         17 $module_with_prefix = $module;
60             }
61              
62             # XXX option load=0?
63 17         76 (my $module_with_prefix_pm = "$module_with_prefix.pm") =~ s!::!/!g;
64 17 100       30 if ($try_all) {
65 2 100       3 eval { require $module_with_prefix_pm }; last unless $@;
  2         1047  
  2         257  
66 1 50       7 warn $@ if $@ !~ /\ACan't locate/;
67             } else {
68 15         1756 require $module_with_prefix_pm;
69             }
70             }
71 12 50       458 if ($@) {
72 0         0 die "load_module_with_optional_args(): Failed to load module '$module' (all prefixes tried: ".join(", ", @ns_prefixes).")";
73             }
74 12         18 $module = $module_with_prefix;
75              
76 12 100       46 my $do_import = defined $opts->{import} ? $opts->{import} : 1;
77 12 100       25 if ($do_import) {
78 8         774 eval "package $target_package; $module->import(\@{\$args});"; ## no critic: BuiltinFunctions::ProhibitStringyEval
79 8 100       464 die if $@;
80             }
81              
82 11         61 {module=>$module, args=>$args};
83             }
84              
85             sub instantiate_class_with_optional_args {
86 3 100   3 1 9184 my $opts = ref($_[0]) eq 'HASH' ? {%{shift()}} : {}; # shallow copy
  2         5  
87 3         7 my $class_with_optional_args = shift;
88              
89 3         5 $opts->{import} = 0;
90 3         9 $opts->{target_package} = caller(0);
91 3         46 my $res = load_module_with_optional_args($opts, $class_with_optional_args);
92 3         6 my $class = $res->{module};
93 3         6 my $args = $res->{args};
94              
95 3 100       7 my $do_construct = defined $opts->{construct} ? $opts->{construct} : 1;
96 3 100       6 if ($do_construct) {
97             my $constructor = defined $opts->{constructor} ?
98 2 100       7 $opts->{constructor} : 'new';
99 2         10 my $obj = $class->$constructor(@$args);
100 2         28 return $obj;
101             } else {
102 1         5 return +{class=>$class, args=>$args};
103             }
104             }
105              
106             1;
107             # ABSTRACT: Some utility routines related to module loading
108              
109             __END__