File Coverage

blib/lib/Data/ModeMerge/Config.pm
Criterion Covered Total %
statement 7 7 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 11 11 100.0


line stmt bran cond sub pod time code
1             package Data::ModeMerge::Config;
2              
3             our $DATE = '2016-02-25'; # DATE
4             our $VERSION = '0.33'; # VERSION
5              
6 31     31   749 use 5.010;
  31         84  
7 31     31   135 use Mo qw(build default);
  31         46  
  31         171  
8              
9             has recurse_hash => (is => 'rw', default => sub{1});
10             has recurse_array => (is => 'rw', default => sub{0});
11             has parse_prefix => (is => 'rw', default => sub{1});
12             has wanted_path => (is => 'rw');
13             has default_mode => (is => 'rw', default => sub{'NORMAL'});
14             has disable_modes => (is => 'rw');
15             has allow_create_array => (is => 'rw', default => sub{1});
16             has allow_create_hash => (is => 'rw', default => sub{1});
17             has allow_destroy_array => (is => 'rw', default => sub{1});
18             has allow_destroy_hash => (is => 'rw', default => sub{1});
19             has exclude_parse => (is => 'rw');
20             has exclude_parse_regex => (is => 'rw');
21             has include_parse => (is => 'rw');
22             has include_parse_regex => (is => 'rw');
23             has exclude_merge => (is => 'rw');
24             has exclude_merge_regex => (is => 'rw');
25             has include_merge => (is => 'rw');
26             has include_merge_regex => (is => 'rw');
27             has set_prefix => (is => 'rw');
28             has readd_prefix => (is => 'rw', default => sub{1});
29             has premerge_pair_filter => (is => 'rw');
30             has options_key => (is => 'rw', default => sub{''});
31             has allow_override => (is => 'rw');
32             has disallow_override => (is => 'rw');
33              
34             # list of config settings only available in merger-object's config
35             # (not in options key)
36             sub _config_config {
37 58     58   156 state $a = [qw/
38             wanted_path
39             options_key
40             allow_override
41             disallow_override
42             /];
43             }
44              
45             # list of config settings available in options key
46             sub _config_ok {
47 54     54   119 state $a = [qw/
48             recurse_hash
49             recurse_array
50             parse_prefix
51             default_mode
52             disable_modes
53             allow_create_array
54             allow_create_hash
55             allow_destroy_array
56             allow_destroy_hash
57             exclude_parse
58             exclude_parse_regex
59             include_parse
60             include_parse_regex
61             exclude_merge
62             exclude_merge_regex
63             include_merge
64             include_merge_regex
65             set_prefix
66             readd_prefix
67             premerge_pair_filter
68             /];
69             }
70              
71             1;
72             # ABSTRACT: Data::ModeMerge configuration
73              
74             __END__
75              
76             =pod
77              
78             =encoding UTF-8
79              
80             =head1 NAME
81              
82             Data::ModeMerge::Config - Data::ModeMerge configuration
83              
84             =head1 VERSION
85              
86             This document describes version 0.33 of Data::ModeMerge::Config (from Perl distribution Data-ModeMerge), released on 2016-02-25.
87              
88             =head1 SYNOPSIS
89              
90             # getting configuration
91             if ($mm->config->allow_extra_hash_keys) { ... }
92              
93             # setting configuration
94             $mm->config->max_warnings(100);
95              
96             =head1 DESCRIPTION
97              
98             Configuration variables for Data::ModeMerge.
99              
100             =head1 ATTRIBUTES
101              
102             =head2 recurse_hash => BOOL
103              
104             Context: config, options key
105              
106             Default: 1
107              
108             Whether to recursively merge hash. When 1, each key-value pair between
109             2 hashes will be recursively merged. Otherwise, the right-side hash
110             will just replace the left-side.
111              
112             Options key will not be parsed under recurse_hash=0.
113              
114             Example:
115              
116             mode_merge({h=>{a=>1}}, {h=>{b=>1}} ); # {h=>{a=>1, b=>1}}
117             mode_merge({h=>{a=>1}}, {h=>{b=>1}}, {recurse_hash=>0}); # {h=>{b=>1}}
118              
119             =head2 recurse_array => BOOL
120              
121             Context: config, options key
122              
123             Default: 0
124              
125             Whether to recursively merge array. When 1, each element is
126             recursively merged. Otherwise, the right-side array will just replace
127             the left-side.
128              
129             Example:
130              
131             mode_merge([1, 1], [4] ); # [4, 1]
132             mode_merge([1, 1], [4], {recurse_array=>0}); # [2]
133              
134             =head2 parse_prefix => BOOL
135              
136             Context: config, options key
137              
138             Default: 1
139              
140             Whether to parse merge prefix in hash keys. If set to 0, merging
141             behaviour is similar to most other nested merge modules.
142              
143             mode_merge({a=>1}, {"+a"=>2} ); # {a=>3}
144             mode_merge({a=>1}, {"+a"=>2}, {parse_prefix=>0}); # {a=>1, "+a"=>2}
145              
146             =head2 wanted_path => ARRAYREF
147              
148             Context: config, options key
149              
150             Default: undef
151              
152             If set, merging is only done to the specified "branch". Useful to save
153             time/storage when merging large hash "trees" while you only want a
154             certain branch of the trees (e.g. resolving just a config variable
155             from several config hashes).
156              
157             Example:
158              
159             mode_merge(
160             {
161             user => {
162             jajang => { quota => 100, admin => 1 },
163             paijo => { quota => 50, admin => 0 },
164             kuya => { quota => 150, admin => 0 },
165             },
166             groups => [qw/admin staff/],
167             },
168             {
169             user => {
170             jajang => { quota => 1000 },
171             }
172             }
173             );
174              
175             With wanted_path unset, the result would be:
176              
177             {
178             user => {
179             jajang => { quota => 1000, admin => 1 },
180             paijo => { quota => 50, admin => 0 },
181             kuya => { quota => 150, admin => 0 },
182             }
183             groups => [qw/admin staff/],
184             }
185              
186             With wanted_path set to ["user", "jajang", "quota"] (in other words,
187             you're saying that you'll be disregarding other branches), the result
188             would be:
189              
190             {
191             user => {
192             jajang => { quota => 1000, admin => undef },
193             }
194             }
195              
196             =head2 default_mode => 'NORMAL' | 'ADD' | 'CONCAT' | 'SUBTRACT' | 'DELETE' | 'KEEP' | ...
197              
198             Context: config, options key
199              
200             Default: NORMAL
201              
202             Example:
203              
204             mode_merge(3, 4 ); # 4
205             mode_merge(3, 4, {default_mode => "ADD"}); # 7
206              
207             =head2 disable_modes => ARRAYREF
208              
209             Context: config, options key
210              
211             Default: []
212              
213             List of modes to ignore the prefixes of.
214              
215             Example:
216              
217             mode_merge({add=>1, del=>2, concat=>3},
218             {add=>2, "!del"=>0, .concat=>4},
219             {disable_modes=>[qw/CONCAT/]});
220             # {add=>3, concat=>3, .concat=>4}
221              
222             See also: C<parse_prefix> which if set to 0 will in effect disable all
223             modes except the default mode.
224              
225             =head2 allow_create_array => BOOL
226              
227             Context: config, options key
228              
229             Default: 1
230              
231             If enabled, then array creation will be allowed (from something
232             non-array, like a hash/scalar). Setting to 0 is useful if you want to
233             avoid the merge to "change the structure" of the left side.
234              
235             Example:
236              
237             mode_merge(1, [1,2] ); # success, result=[1,2]
238             mode_merge(1, [1,2], {allow_create_array=>0}); # failed, can't create array
239              
240             =head2 allow_create_hash => BOOL
241              
242             Context: config, options key
243              
244             Default: 1
245              
246             If enabled, then hash creation will be allowed (from something
247             non-hash, like array/scalar). Setting to 0 is useful if you want to
248             avoid the merge to "change the structure" of the left side.
249              
250             Example:
251              
252             mode_merge(1, {a=>1} ); # success, result={a=>1}
253             mode_merge(1, {a=>1}, {allow_create_hash=>0}); # failed, can't create hash
254              
255             =head2 allow_destroy_array => BOOL
256              
257             Context: config, options key
258              
259             Default: 1
260              
261             If enabled, then replacing array on the left side with non-array
262             (e.g. hash/scalar) on the right side is allowed. Setting to 0 is
263             useful if you want to avoid the merge to "change the structure" of the
264             left side.
265              
266             Example:
267              
268             mode_merge([1,2], {} ); # success, result={}
269             mode_merge([1,2], {}, {allow_destroy_array=>0}); # failed, can't destroy array
270              
271             =head2 allow_destroy_hash => BOOL
272              
273             Context: config, options key
274              
275             Default: 1
276              
277             If enabled, then replacing hash on the left side with non-hash
278             (e.g. array/scalar) on the right side is allowed. Setting to 0 is
279             useful if you want to avoid the merge to "change the structure" of the
280             left side.
281              
282             Example:
283              
284             mode_merge({a=>1}, [] ); # success, result=[]
285             mode_merge({a=>1}, [], {allow_destroy_hash=>0}); # failed, can't destroy hash
286              
287             =head2 exclude_parse => ARRAYREF
288              
289             Context: config, options key
290              
291             Default: undef
292              
293             The list of hash keys that should not be parsed for prefix and merged
294             as-is using the default mode.
295              
296             If C<include_parse> is also mentioned then only keys in
297             C<include_parse> and not in C<exclude_parse> will be parsed for
298             prefix.
299              
300             Example:
301              
302             mode_merge({a=>1, b=>2}, {"+a"=>3, "+b"=>4}, {exclude_parse=>["+b"]}); # {a=>4, b=>2, "+b"=>4}
303              
304             =head2 exclude_parse_regex => REGEX
305              
306             Context: config, options key
307              
308             Default: undef
309              
310             Just like C<exclude_parse> but using regex instead of list.
311              
312             =head2 include_parse => ARRAYREF
313              
314             Context: config, options key
315              
316             Default: undef
317              
318             If specified, then only hash keys listed by this setting will be
319             parsed for prefix. The rest of the keys will not be parsed and merged
320             as-is using the default mode.
321              
322             If C<exclude_parse> is also mentioned then only keys in
323             C<include_parse> and not in C<exclude_parse> will be parsed for
324             prefix.
325              
326             Example:
327              
328             mode_merge({a=>1, b=>2, c=>3}, {"+a"=>4, "+b"=>5, "+c"=>6},
329             {include_parse=>["+a"]}); # {a=>1, "+a"=>4, b=>7, c=>3, "+c"=>6}
330              
331             =head2 include_parse_regex => REGEX
332              
333             Context: config, options key
334              
335             Default: undef
336              
337             Just like C<include_parse> but using regex instead of list.
338              
339             =head2 exclude_merge => ARRAYREF
340              
341             Context: config, options key
342              
343             Default: undef
344              
345             The list of hash keys on the left side that should not be merged and
346             instead copied directly to the result. All merging keys on the right
347             side will be ignored.
348              
349             If C<include_merge> is also mentioned then only keys in
350             C<include_merge> and not in C<exclude_merge> will be merged.
351              
352             Example:
353              
354             mode_merge({a=>1}, {"+a"=>20, "-a"=>30}, {exclude_merge=>["a"]}); # {a=>1}
355              
356             =head2 exclude_merge_regex => REGEX
357              
358             Context: config, options key
359              
360             Default: undef
361              
362             Just like C<exclude_merge> but using regex instead of list.
363              
364             =head2 include_merge => ARRAYREF
365              
366             Context: config, options key
367              
368             Default: undef
369              
370             If specified, then only hash keys listed by this setting will be
371             merged.
372              
373             If C<exclude_merge> is also mentioned then only keys in
374             C<include_merge> and not in C<exclude_merge> will be merged.
375              
376             Example:
377              
378             mode_merge({a=>1, b=>2, c=>3}, {"+a"=>40, "+b"=>50, "+c"=>60, "!c"=>70},
379             {include_merge=>["a"]}); # {a=>41, b=>2, c=>3}
380              
381             =head2 include_merge_regex => ARRAYREF
382              
383             Context: config, options key
384              
385             Default: undef
386              
387             Just like C<include_merge> but using regex instead of list.
388              
389             =head2 set_prefix => HASHREF
390              
391             Context: config, options key
392              
393             Default: undef
394              
395             Temporarily change the prefix character for each mode. Value is
396             hashref where each hash key is mode and the value is a new prefix
397             string.
398              
399             mode_merge({a=>1, c=>2}, {'+a'=>10, '.c'=>20}); # {a=>11, c=>220}
400             mode_merge({a=>1, c=>2}, {'+a'=>10, '.c'=>20}, {set_prefix=>{ADD=>'.', CONCAT=>'+'}}); # {a=>110, c=>22}
401              
402             =head2 readd_prefix => BOOL
403              
404             Context: config, options key
405              
406             Default: 1
407              
408             When merging two hashes, the prefixes are first stripped before
409             merging. After merging is done, the prefixes by default will be
410             re-added. This is done so that modes which are "sticky" (like KEEP)
411             can propagate their mode). Setting C<readd_prefix> to 0 will prevent
412             their stickiness.
413              
414             mode_merge({"^a"=>1}, {a=>2}); # {"^a"=>1}
415             mode_merge({"^a"=>1}, {a=>2}, {readd_prefix=>0}); # { "a"=>1}
416              
417             =head2 premerge_pair_filter => CODEREF
418              
419             Context: config, options key
420              
421             Default: undef
422              
423             Pass the key and value of each hash pair to a subroutine before
424             merging (and before the keys are stripped for mode prefixes). Will
425             push error if there is conflicting key in the hash.
426              
427             The subroutine should return a list of new key(s) and value(s). If key
428             is undef then it means the pair should be discarded. This way, the
429             filter is able to add or remove pairs from the hash.
430              
431             mode_merge({a=>1}, {"+amok"=>2},
432             {premerge_pair_filter=>sub{ uc(substr($_[0],0,2)), $_[1]*2 }});
433             # {"A"=>6}
434              
435             =head2 options_key => STR
436              
437             Context: config
438              
439             Default: '' (empty string)
440              
441             If defined, then when merging two hashes, this key will be searched
442             first on the left-side and right-side hash. The values will then be
443             merged and override (many of) the configuration.
444              
445             Options key is analogous to Apache's C<.htaccess> mechanism, which
446             allows setting configuration on a per-directory (per-hash)
447             basis. There's even an C<allow_override> config similar to Apache
448             directive of the same name.
449              
450             If you want to disable processing of options key, set this to undef.
451              
452             Example:
453              
454             mode_merge({a=>1, {x=>3}},
455             {a=>2, {x=>4}},
456             {default_mode=>'ADD'}); # {a=>3, {x=>7}}
457             mode_merge({a=>1, {x=>3}},
458             {a=>2, {x=>4, ''=>{default_mode=>'CONCAT'}}},
459             {default_mode=>'ADD'}); # {a=>3, {x=>34}}
460              
461             On the above example, C<default_mode> is set to ADD. But in the
462             {x=>...} subhash, C<default_mode> is changed to CONCAT by the options
463             key.
464              
465             =head2 allow_override => REGEX
466              
467             Context: config
468              
469             Default: undef
470              
471             If defined, then only config names matching regex will be able to be
472             set in options key.
473              
474             If C<disallow_override> is also set, then only config names matching
475             C<allow_override> and not matching C<disallow_override> will be able
476             to be set in options key.
477              
478             =head2 disallow_override => REGEX
479              
480             Context: config
481              
482             Default: undef
483              
484             If defined, then config names matching regex will not be able to be
485             set in options key.
486              
487             For example, if you want to restrict "structural changes" in merging
488             while still allowing options key, you can set C<allow_create_hash>,
489             C<allow_destroy_hash>, C<allow_create_array>, and
490             C<allow_destroy_array> all to 0 and C<disallow_override> to
491             C<allow_create|allow_destroy> to forbid overriding via options key.
492              
493             If C<disallow_override> is also set, then only config names matching
494             C<allow_override> and not matching C<disallow_override> will be able
495             to be set in options key.
496              
497             =head1 HOMEPAGE
498              
499             Please visit the project's homepage at L<https://metacpan.org/release/Data-ModeMerge>.
500              
501             =head1 SOURCE
502              
503             Source repository is at L<https://github.com/perlancar/perl-Data-ModeMerge>.
504              
505             =head1 BUGS
506              
507             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Data-ModeMerge>
508              
509             When submitting a bug or request, please include a test-file or a
510             patch to an existing test-file that illustrates the bug or desired
511             feature.
512              
513             =head1 AUTHOR
514              
515             perlancar <perlancar@cpan.org>
516              
517             =head1 COPYRIGHT AND LICENSE
518              
519             This software is copyright (c) 2016 by perlancar@cpan.org.
520              
521             This is free software; you can redistribute it and/or modify it under
522             the same terms as the Perl 5 programming language system itself.
523              
524             =cut