File Coverage

blib/lib/Path/Resolver/Resolver/Mux/Prefix.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 16 16 100.0


line stmt bran cond sub pod time code
1             package Path::Resolver::Resolver::Mux::Prefix 3.100455;
2             # ABSTRACT: multiplex resolvers by using path prefix
3 1     1   482 use Moose;
  1         2  
  1         6  
4              
5 1     1   5548 use namespace::autoclean;
  1         2  
  1         7  
6              
7 1     1   60 use MooseX::Types;
  1         2  
  1         8  
8 1     1   3555 use MooseX::Types::Moose qw(Any HashRef);
  1         2  
  1         9  
9              
10             #pod =head1 SYNOPSIS
11             #pod
12             #pod my $resolver = Path::Resolver::Resolver::Mux::Prefix->new({
13             #pod prefixes => {
14             #pod foo => $foo_resolver,
15             #pod bar => $bar_resolver,
16             #pod },
17             #pod });
18             #pod
19             #pod my $simple_entity = $resolver->entity_at('foo/bar.txt');
20             #pod
21             #pod This resolver looks at the first part of paths it's given to resolve. It uses
22             #pod that part to find a resolver (by looking it up in the C<prefixes>) and then
23             #pod uses that resolver to resolver the rest of the path.
24             #pod
25             #pod The default native type of this resolver is Any, meaning that is is much more
26             #pod lax than other resolvers. A C<native_type> can be specified while creating the
27             #pod resolver.
28             #pod
29             #pod =head1 WHAT'S THE POINT?
30             #pod
31             #pod This multiplexer allows you to set up a virtual filesystem in which each
32             #pod subtree is handled by a different resolver. For example:
33             #pod
34             #pod my $resolver = Path::Resolver::Resolver::Mux::Prefix->new({
35             #pod config => Path::Resolver::Resolver::FileSystem->new({
36             #pod root => '/etc/my-app',
37             #pod }),
38             #pod
39             #pod template => Path::Resolver::Resolver::Mux::Ordered->new({
40             #pod Path::Resolver::Resolver::DistDir->new({ module => 'MyApp' }),
41             #pod Path::Resolver::Resolver::DataSection->new({ module => 'My::Framework' }),
42             #pod }),
43             #pod });
44             #pod
45             #pod The path F</config/main.cf> would be looked for on disk as
46             #pod F</etc/my-app/main.cf>. The path F</template/main.html> would be looked for
47             #pod first as F<main.html> in the sharedir for MyApp and failing that in the DATA
48             #pod section of My::Framework.
49             #pod
50             #pod This kind of resolver allows you to provide a very simple API (that is,
51             #pod filenames) to find all manner of resources, either files or otherwise.
52             #pod
53             #pod =attr prefixes
54             #pod
55             #pod This is a hashref of path prefixes with the resolver that should be used for
56             #pod paths under that prefix. If a resolver is given for the empty prefix, it will
57             #pod be used for content that did not begin with registered prefix.
58             #pod
59             #pod =method get_resolver_for
60             #pod
61             #pod This method gets the resolver for the named prefix.
62             #pod
63             #pod =method set_resolver_for
64             #pod
65             #pod This method sets the resolver for the named prefix, replacing any that already
66             #pod existed.
67             #pod
68             #pod =method add_resolver_for
69             #pod
70             #pod This method sets the resolver for the named prefix, throwing an exception if
71             #pod one already exists.
72             #pod
73             #pod =method has_resolver_for
74             #pod
75             #pod This method returns true if a resolver exists for the given prefix.
76             #pod
77             #pod =method delete_resolver_for
78             #pod
79             #pod This method deletes the resolver for the named prefix.
80             #pod
81             #pod =cut
82              
83             has prefixes => (
84             is => 'ro',
85             isa => HashRef[ role_type('Path::Resolver::Role::Resolver') ],
86             required => 1,
87             traits => ['Hash'],
88             handles => {
89             get_resolver_for => 'get',
90             set_resolver_for => 'set',
91             add_resolver_for => 'set',
92             has_resolver_for => 'exists',
93             delete_resolver_for => 'delete',
94             },
95             );
96              
97             before add_resolver_for => sub {
98             confess "a resolver for $_[1] already exists"
99             if $_[0]->has_resolver_for($_[1]);
100             };
101              
102             has native_type => (
103             is => 'ro',
104             isa => class_type('Moose::Meta::TypeConstraint'),
105             required => 1,
106             default => sub { Any },
107             );
108              
109             with 'Path::Resolver::Role::Resolver';
110              
111             sub entity_at {
112             my ($self, $path) = @_;
113             my @path = @$path;
114              
115             shift @path if $path[0] eq '';
116              
117             if (my $resolver = $self->prefixes->{ $path[0] }) {
118             shift @path;
119             return $resolver->entity_at(\@path);
120             }
121              
122             return unless my $resolver = $self->prefixes->{ '' };
123              
124             return $resolver->entity_at(\@path);
125             }
126              
127             1;
128              
129             __END__
130              
131             =pod
132              
133             =encoding UTF-8
134              
135             =head1 NAME
136              
137             Path::Resolver::Resolver::Mux::Prefix - multiplex resolvers by using path prefix
138              
139             =head1 VERSION
140              
141             version 3.100455
142              
143             =head1 SYNOPSIS
144              
145             my $resolver = Path::Resolver::Resolver::Mux::Prefix->new({
146             prefixes => {
147             foo => $foo_resolver,
148             bar => $bar_resolver,
149             },
150             });
151              
152             my $simple_entity = $resolver->entity_at('foo/bar.txt');
153              
154             This resolver looks at the first part of paths it's given to resolve. It uses
155             that part to find a resolver (by looking it up in the C<prefixes>) and then
156             uses that resolver to resolver the rest of the path.
157              
158             The default native type of this resolver is Any, meaning that is is much more
159             lax than other resolvers. A C<native_type> can be specified while creating the
160             resolver.
161              
162             =head1 PERL VERSION
163              
164             This library should run on perls released even a long time ago. It should work
165             on any version of perl released in the last five years.
166              
167             Although it may work on older versions of perl, no guarantee is made that the
168             minimum required version will not be increased. The version may be increased
169             for any reason, and there is no promise that patches will be accepted to lower
170             the minimum required perl.
171              
172             =head1 ATTRIBUTES
173              
174             =head2 prefixes
175              
176             This is a hashref of path prefixes with the resolver that should be used for
177             paths under that prefix. If a resolver is given for the empty prefix, it will
178             be used for content that did not begin with registered prefix.
179              
180             =head1 METHODS
181              
182             =head2 get_resolver_for
183              
184             This method gets the resolver for the named prefix.
185              
186             =head2 set_resolver_for
187              
188             This method sets the resolver for the named prefix, replacing any that already
189             existed.
190              
191             =head2 add_resolver_for
192              
193             This method sets the resolver for the named prefix, throwing an exception if
194             one already exists.
195              
196             =head2 has_resolver_for
197              
198             This method returns true if a resolver exists for the given prefix.
199              
200             =head2 delete_resolver_for
201              
202             This method deletes the resolver for the named prefix.
203              
204             =head1 WHAT'S THE POINT?
205              
206             This multiplexer allows you to set up a virtual filesystem in which each
207             subtree is handled by a different resolver. For example:
208              
209             my $resolver = Path::Resolver::Resolver::Mux::Prefix->new({
210             config => Path::Resolver::Resolver::FileSystem->new({
211             root => '/etc/my-app',
212             }),
213              
214             template => Path::Resolver::Resolver::Mux::Ordered->new({
215             Path::Resolver::Resolver::DistDir->new({ module => 'MyApp' }),
216             Path::Resolver::Resolver::DataSection->new({ module => 'My::Framework' }),
217             }),
218             });
219              
220             The path F</config/main.cf> would be looked for on disk as
221             F</etc/my-app/main.cf>. The path F</template/main.html> would be looked for
222             first as F<main.html> in the sharedir for MyApp and failing that in the DATA
223             section of My::Framework.
224              
225             This kind of resolver allows you to provide a very simple API (that is,
226             filenames) to find all manner of resources, either files or otherwise.
227              
228             =head1 AUTHOR
229              
230             Ricardo Signes <cpan@semiotic.systems>
231              
232             =head1 COPYRIGHT AND LICENSE
233              
234             This software is copyright (c) 2022 by Ricardo Signes.
235              
236             This is free software; you can redistribute it and/or modify it under
237             the same terms as the Perl 5 programming language system itself.
238              
239             =cut