File Coverage

lib/Mojolicious/Plugin/Fondation/Utils.pm
Criterion Covered Total %
statement 50 51 98.0
branch 10 12 83.3
condition 6 6 100.0
subroutine 10 10 100.0
pod 0 5 0.0
total 76 84 90.4


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::Fondation::Utils;
2             $Mojolicious::Plugin::Fondation::Utils::VERSION = '0.03';
3             # ABSTRACT: Utility functions: config merge, name resolution, share directory helpers
4              
5 15     15   84691 use Mojo::Base -strict, -signatures;
  15         8587  
  15         99  
6 15     15   13177 use File::ShareDir 'dist_dir';
  15         335944  
  15         840  
7 15     15   6714 use Hash::Merge ();
  15         93676  
  15         387  
8 15     15   913 use Mojo::File;
  15         322346  
  15         690  
9              
10 15     15   66 use Exporter 'import';
  15         28  
  15         9277  
11             our @EXPORT_OK = qw( long_name short_name share_relative find_share_dir merge);
12              
13             sub long_name {
14 212     212 0 356 my ($name) = @_;
15 212 100       533 return $name if $name =~ /^Mojolicious::Plugin::/;
16 203         712 return "Mojolicious::Plugin::$name";
17             }
18              
19             sub short_name {
20 246     246 0 431 my ($name) = @_;
21 246         580 $name =~ s/^Mojolicious::Plugin:://;
22 246         493 return $name;
23             }
24              
25             sub share_relative {
26 107     107 0 493 my ($path) = @_;
27             # Normalize to forward slashes (cross-platform: Windows uses backslashes)
28 107         274 (my $normalized = $path) =~ s{\\}{/}g;
29 107         523 my $pos = rindex($normalized, '/share/');
30 107 100       558 return $path if $pos == -1;
31 106         247 return substr($normalized, $pos + 1);
32             }
33              
34 161     161 0 225 sub find_share_dir ($class_name, $override = undef) {
  161         261  
  161         298  
  161         192  
35 161 100       474 return Mojo::File->new($override) if $override;
36              
37 118         188 my $dist = $class_name;
38 118         437 $dist =~ s/::/-/g;
39              
40             # 1) Try File::ShareDir (installed modules)
41 118         199 my $dir = eval { Mojo::File->new(dist_dir($dist)) };
  118         476  
42 118 100       29110 return $dir if $dir;
43              
44             # 2) Fallback: derive share dir from the class's location in %INC
45             # This handles test/dev environments where the module is not yet installed.
46 52         264 (my $rel_path = "$class_name.pm") =~ s{::}{/}g;
47 52 50       175 if (my $inc_path = $INC{$rel_path}) {
48 52         241 my $pm = Mojo::File->new($inc_path);
49 52         474 my $root = $pm;
50 52         149 my $levels = scalar(split /::/, $class_name) + 1; # +1 for lib/
51 52         258 $root = $root->dirname for 1 .. $levels;
52 52         7952 my $share = $root->child('share');
53 52 50       776 return $share if -d $share;
54             }
55              
56             # 3) Last resort
57 0         0 return Mojo::File->curfile->sibling('share');
58             }
59              
60             # 3-level merging with priority (uses Hash::Merge for recursive merge):
61             # 1. direct config (in dependencies list) -- highest priority
62             # 2. config in the app file (myapp.conf)
63             # 3. plugin defaults (via fondation_meta) -- lowest priority
64             #
65             # Hash::Merge::merge() is LEFT_PRECEDENT, so we reverse the call order:
66             # merge(direct, merge(app_conf, defaults))
67             # -> direct wins over app_conf wins over defaults for scalars
68             # -> arrays are concatenated, hashes are merged recursively
69 264     264 0 191960 sub merge ($direct = {}, $app_conf = {}, $plugin_defaults = {}) {
  264         360  
  264         380  
  264         352  
  264         309  
70 264   100     1166 return Hash::Merge::merge(
      100        
      100        
71             $direct // {},
72             Hash::Merge::merge($app_conf // {}, $plugin_defaults // {})
73             );
74             }
75              
76             1;
77              
78             __END__