1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
package Config::MVP::Assembler::WithBundles;
BEGIN {
$Config::MVP::Assembler::WithBundles::VERSION = '2.101650';
}
use Moose::Role;
# ABSTRACT: a role to make assemblers expand bundles
use Params::Util qw(_HASHLIKE _ARRAYLIKE);
sub package_bundle_method {
my ($self, $pkg) = @_;
return unless $pkg->can('mvp_bundle_config');
return 'mvp_bundle_config';
}
after end_section => sub {
my ($self) = @_;
my $seq = $self->sequence;
my ($last) = ($seq->sections)[-1];
return unless $last->package;
return unless my $method = $self->package_bundle_method($last->package);
$self->replace_bundle_with_contents($last, $method);
};
sub replace_bundle_with_contents {
my ($self, $bundle_sec, $method) = @_;
my $seq = $self->sequence;
$seq->delete_section($bundle_sec->name);
$self->_add_bundle_contents($method, {
name => $bundle_sec->name,
package => $bundle_sec->package,
payload => $bundle_sec->payload,
});
};
sub _add_bundle_contents {
my ($self, $method, $arg) = @_;
my @bundle_config = $arg->{package}->$method($arg);
PLUGIN: for my $plugin (@bundle_config) {
my ($name, $package, $payload) = @$plugin;
Class::MOP::load_class($package);
if (my $method = $self->package_bundle_method( $package )) {
$self->_add_bundle_contents($method, {
name => $name,
package => $package,
payload => $payload,
});
} else {
my $section = $self->section_class->new({
name => $name,
package => $package,
});
if (_HASHLIKE($payload)) {
# XXX: Clearly this is a hack. -- rjbs, 2009-08-24
for my $name (keys %$payload) {
my @v = ref $payload->{$name}
? @{$payload->{$name}}
: $payload->{$name};
$section->add_value($name => $_) for @v;
}
} elsif (_ARRAYLIKE($payload)) {
for (my $i = 0; $i < @$payload; $i += 2) {
$section->add_value(@$payload[ $i, $i + 1 ]);
}
} else {
Carp::confess("don't know how to interpret section payload $payload");
}
$self->sequence->add_section($section);
$section->finalize;
}
}
}
no Moose;
1;
__END__
=pod
=head1 NAME
Config::MVP::Assembler::WithBundles - a role to make assemblers expand bundles
=head1 VERSION
version 2.101650
=head1 DESCRIPTION
Config::MVP::Assembler::WithBundles is a role to be composed into a
Config::MVP::Assembler subclass. It allows some sections of configuration to
be treated as bundles. When any section is ended, if that section represented
a bundle, its bundle contents will be unrolled and will replace it in the
sequence.
A package is considered a bundle if the this returns a defined method:
my $method = $assembler->package_bundle_method($package);
The default implementation looks for a method callde C<mvp_bundle_config>, but
C<package_bundle_method> can be replaced to allow for other bundle-identifying
information.
Bundles are expanded by a call to the assembler's
C<replace_bundle_with_contents> method, like this:
$assembler->replace_bundle_with_contents($section, $method);
=head2 replace_bundle_with_contents
The default C<replace_bundle_with_contents> method deletes the section from the
sequence. It then gets a description of the new sections to introduce, like
this:
my @new_config = $bundle_section->package->$method({
name => $bundle_section->name,
package => $bundle_section->package,
payload => $bundle_section->payload,
});
(We pass a hashref rather than a section so that bundles can be expanded
synthetically without having to laboriously create a new Section.)
The returned C<@new_config> is a list of arrayrefs, each of which has three
entries:
[ $name, $package, $payload ]
Each arrayref is converted into a section in the sequence. The C<$payload>
should be an arrayref of name/value pairs to be added to the created section.
=head1 AUTHOR
Ricardo Signes <rjbs@cpan.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2010 by Ricardo Signes.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
|