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.02';
3             # ABSTRACT: Utility functions: config merge, name resolution, share directory helpers
4              
5 15     15   80706 use Mojo::Base -strict, -signatures;
  15         8408  
  15         106  
6 15     15   13231 use File::ShareDir 'dist_dir';
  15         361966  
  15         919  
7 15     15   6736 use Hash::Merge ();
  15         101782  
  15         388  
8 15     15   881 use Mojo::File;
  15         350190  
  15         727  
9              
10 15     15   75 use Exporter 'import';
  15         26  
  15         9315  
11             our @EXPORT_OK = qw( long_name short_name share_relative find_share_dir merge);
12              
13             sub long_name {
14 212     212 0 368 my ($name) = @_;
15 212 100       572 return $name if $name =~ /^Mojolicious::Plugin::/;
16 203         673 return "Mojolicious::Plugin::$name";
17             }
18              
19             sub short_name {
20 246     246 0 432 my ($name) = @_;
21 246         615 $name =~ s/^Mojolicious::Plugin:://;
22 246         479 return $name;
23             }
24              
25             sub share_relative {
26 107     107 0 511 my ($path) = @_;
27             # Normalize to forward slashes (cross-platform: Windows uses backslashes)
28 107         276 (my $normalized = $path) =~ s{\\}{/}g;
29 107         577 my $pos = rindex($normalized, '/share/');
30 107 100       671 return $path if $pos == -1;
31 106         276 return substr($normalized, $pos + 1);
32             }
33              
34 161     161 0 226 sub find_share_dir ($class_name, $override = undef) {
  161         235  
  161         297  
  161         208  
35 161 100       534 return Mojo::File->new($override) if $override;
36              
37 118         154 my $dist = $class_name;
38 118         447 $dist =~ s/::/-/g;
39              
40             # 1) Try File::ShareDir (installed modules)
41 118         223 my $dir = eval { Mojo::File->new(dist_dir($dist)) };
  118         500  
42 118 100       30440 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         265 (my $rel_path = "$class_name.pm") =~ s{::}{/}g;
47 52 50       225 if (my $inc_path = $INC{$rel_path}) {
48 52         245 my $pm = Mojo::File->new($inc_path);
49 52         490 my $root = $pm;
50 52         175 my $levels = scalar(split /::/, $class_name) + 1; # +1 for lib/
51 52         293 $root = $root->dirname for 1 .. $levels;
52 52         7772 my $share = $root->child('share');
53 52 50       813 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 188269 sub merge ($direct = {}, $app_conf = {}, $plugin_defaults = {}) {
  264         370  
  264         339  
  264         331  
  264         316  
70 264   100     1251 return Hash::Merge::merge(
      100        
      100        
71             $direct // {},
72             Hash::Merge::merge($app_conf // {}, $plugin_defaults // {})
73             );
74             }
75              
76             1;
77              
78             __END__