File Coverage

blib/lib/Hades/Myths/Object.pm
Criterion Covered Total %
statement 127 140 90.7
branch 83 102 81.3
condition 36 51 70.5
subroutine 19 20 95.0
pod 10 10 100.0
total 275 323 85.1


line stmt bran cond sub pod time code
1             package Hades::Myths::Object;
2 15     15   75323 use strict;
  15         41  
  15         437  
3 15     15   82 use warnings;
  15         28  
  15         434  
4 15     15   668 use POSIX qw/locale_h/;
  15         7305  
  15         111  
5             our $VERSION = 0.19;
6              
7             sub new {
8 42 100   42 1 44889 my ( $cls, %args ) = ( shift(), scalar @_ == 1 ? %{ $_[0] } : @_ );
  26         112  
9 42         114 my $self = bless {}, $cls;
10             my %accessors = (
11             locales => {
12             builder => sub {
13 39     39   99 my ( $self, $value ) = @_;
14 39         147 $value = $self->_build_locales($value);
15 37         137 return $value;
16             }
17             },
18             fb => { default => 'en', },
19             locale => {
20             builder => sub {
21 39     39   92 my ( $self, $value ) = @_;
22 39         124 $value = $self->_build_locale($value);
23 37         128 return $value;
24             }
25             },
26 42         490 language => {},
27             );
28 42         166 for my $accessor ( keys %accessors ) {
29             my $param
30             = defined $args{$accessor}
31             ? $args{$accessor}
32 152 100       404 : $accessors{$accessor}->{default};
33             my $value
34             = $self->$accessor( $accessors{$accessor}->{builder}
35 152 100       549 ? $accessors{$accessor}->{builder}->( $self, $param )
36             : $param );
37 143 50 33     433 unless ( !$accessors{$accessor}->{required} || defined $value ) {
38 0         0 die "$accessor accessor is required";
39             }
40             }
41 33         424 return $self;
42             }
43              
44             sub fb {
45 954     954 1 2811 my ( $self, $value ) = @_;
46 954 100       1604 if ( defined $value ) {
47 40 100       126 if ( ref $value ) {
48 4         49 die qq{Str: invalid value $value for accessor fb};
49             }
50 36         104 $self->{fb} = $value;
51             }
52 950         1613 return $self->{fb};
53             }
54              
55             sub locale {
56 953     953 1 3249 my ( $self, $value ) = @_;
57 953 100       1660 if ( defined $value ) {
58 40 100       124 if ( ref $value ) {
59 2         23 die qq{Str: invalid value $value for accessor locale};
60             }
61 38         122 $self->{locale} = $value;
62 38         150 $self->_set_language_from_locale($value);
63             }
64 951         2111 return $self->{locale};
65             }
66              
67             sub _build_locale {
68 41     41   915 my ( $self, $locale ) = @_;
69 41 100       121 if ( defined $locale ) {
70 25 100       85 if ( ref $locale ) {
71 4         53 die
72             qq{Optional[Str]: invalid value $locale for variable \$locale in method _build_locale};
73             }
74             }
75              
76 37   66     264 return $locale || setlocale(LC_CTYPE);
77              
78             }
79              
80             sub _set_language_from_locale {
81 41     41   1442 my ( $self, $value ) = @_;
82 41 100 100     229 if ( !defined($value) || ref $value ) {
83 3 100       9 $value = defined $value ? $value : 'undef';
84 3         45 die
85             qq{Str: invalid value $value for variable \$value in method _set_language_from_locale};
86             }
87              
88 38 100       118 unless ( $self->has_language ) {
89 31         108 my ( $locale, $lang ) = $self->convert_locale($value);
90 31 50       92 if ($lang) { $self->language($lang); }
  31         109  
91             }
92              
93             }
94              
95             sub language {
96 983     983 1 2262 my ( $self, $value ) = @_;
97 983 100       1694 if ( defined $value ) {
98 48 100       139 if ( ref $value ) {
99 2         25 die qq{Str: invalid value $value for accessor language};
100             }
101 46         97 $self->{language} = $value;
102             }
103 981         1751 return $self->{language};
104             }
105              
106             sub has_language {
107 40     40 1 78 my ($self) = @_;
108 40         169 return exists $self->{language};
109             }
110              
111             sub locales {
112 4654     4654 1 10338 my ( $self, $value ) = @_;
113 4654 100       7054 if ( defined $value ) {
114 43 100 100     243 if ( ( ref($value) || "" ) ne "HASH" ) {
115 2         19 die
116             qq{Map[Str, HashRef]: invalid value $value for accessor locales};
117             }
118 41         69 for my $key ( keys %{$value} ) {
  41         368  
119 1829         2244 my $val = $value->{$key};
120 1829 50       2792 if ( ref $key ) {
121 0         0 die
122             qq{Map[Str, HashRef]: invalid value $key for accessor locales expected Str};
123             }
124 1829 100 100     3717 if ( ( ref($val) || "" ) ne "HASH" ) {
125 6 100       18 $val = defined $val ? $val : 'undef';
126 6         80 die
127             qq{Map[Str, HashRef]: invalid value $val for accessor locales expected HashRef};
128             }
129             }
130 35         131 $self->{locales} = $value;
131             }
132 4646         17072 return $self->{locales};
133             }
134              
135             sub _build_locales {
136 41     41   861 my ( $self, $values ) = @_;
137 41 100       114 $values = defined $values ? $values : {};
138 41 100 100     213 if ( ( ref($values) || "" ) ne "HASH" ) {
139 4 50       9 $values = defined $values ? $values : 'undef';
140 4         54 die
141             qq{HashRef: invalid value $values for variable \$values in method _build_locales};
142             }
143              
144 37         122 my ($debug_steps) = debug_steps();
145             return {
146 37         103 %{$values}, %{$debug_steps},
  37         348  
147 37 50       72 ( $self->locales ? ( %{ $self->locales } ) : () )
  0         0  
148             };
149              
150             }
151              
152             sub convert_locale {
153 49     49 1 2177 my ( $self, $locale, $fb ) = @_;
154 49 100 66     232 if ( !defined($locale) || ref $locale ) {
155 2 50       7 $locale = defined $locale ? $locale : 'undef';
156 2         26 die
157             qq{Str: invalid value $locale for variable \$locale in method convert_locale};
158             }
159 47 100       127 $fb = defined $fb ? $fb : "en";
160 47 100 66     213 if ( !defined($fb) || ref $fb ) {
161 2 50       6 $fb = defined $fb ? $fb : 'undef';
162 2         21 die
163             qq{Str: invalid value $fb for variable \$fb in method convert_locale};
164             }
165              
166 45         193 $locale =~ m/^(\w\w)_(\w\w).*/;
167 45 50 33     316 return $1 && $2 ? ( $1 . '_' . $2, $1, $fb ) : ( $locale, $fb, $fb );
168              
169             }
170              
171             sub add {
172 7     7 1 3969 my ( $self, $key, $locales ) = @_;
173 7 100 66     37 if ( !defined($key) || ref $key ) {
174 2 50       9 $key = defined $key ? $key : 'undef';
175 2         26 die qq{Str: invalid value $key for variable \$key in method add};
176             }
177 5 100 100     23 if ( ( ref($locales) || "" ) ne "HASH" ) {
178 2 50       7 $locales = defined $locales ? $locales : 'undef';
179 2         19 die
180             qq{Map[Str, HashRef]: invalid value $locales for variable \$locales in method add};
181             }
182 3         5 for my $key ( keys %{$locales} ) {
  3         12  
183 3         6 my $val = $locales->{$key};
184 3 50       9 if ( ref $key ) {
185 0         0 die
186             qq{Map[Str, HashRef]: invalid value $key for variable \$locales in method add expected Str};
187             }
188 3 50 100     14 if ( ( ref($val) || "" ) ne "HASH" ) {
189 3 100       9 $val = defined $val ? $val : 'undef';
190 3         28 die
191             qq{Map[Str, HashRef]: invalid value $val for variable \$locales in method add expected HashRef};
192             }
193             }
194              
195 0         0 $self->locales->{$key} = { %{ $self->locales->{$key} }, %{$locales} };
  0         0  
  0         0  
196              
197             }
198              
199             sub string {
200 920     920 1 6264 my ( $self, $key, $locale, $lang, $fb ) = @_;
201 920 100 66     3200 if ( !defined($key) || ref $key ) {
202 2 50       8 $key = defined $key ? $key : 'undef';
203 2         37 die qq{Str: invalid value $key for variable \$key in method string};
204             }
205 918 100       2086 $locale = defined $locale ? $locale : $self->locale;
206 918 100 66     2741 if ( !defined($locale) || ref $locale ) {
207 2 50       37 $locale = defined $locale ? $locale : 'undef';
208 2         24 die
209             qq{Str: invalid value $locale for variable \$locale in method string};
210             }
211 916 100       1997 $lang = defined $lang ? $lang : $self->language;
212 916 100 66     2631 if ( !defined($lang) || ref $lang ) {
213 2 50       6 $lang = defined $lang ? $lang : 'undef';
214 2         21 die qq{Str: invalid value $lang for variable \$lang in method string};
215             }
216 914 100       1943 $fb = defined $fb ? $fb : $self->fb;
217 914 100 66     2570 if ( !defined($fb) || ref $fb ) {
218 2 50       5 $fb = defined $fb ? $fb : 'undef';
219 2         21 die qq{Str: invalid value $fb for variable \$fb in method string};
220             }
221              
222             die "string $key is empty"
223             if ( !ref $self->locales->{$key}
224 912 50 33     1505 || !scalar keys %{ $self->locales->{$key} } );
  912         1368  
225             $_ && exists $self->locales->{$key}->{$_}
226             and return $self->locales->{$key}->{$_}
227 912   66     2732 for ( $locale, $lang, $fb );
      100        
228             return $self->locales->{$key}
229 0         0 ->{ [ keys %{ $self->locales->{$key} } ]->[0] };
  0         0  
230              
231             }
232              
233             sub debug_steps {
234 37     37 1 98 my ( $self, $steps ) = @_;
235              
236 37         2299 $steps = {
237             debug_step_1 => { en => 'About to run hades with %s.', },
238             debug_step_2 =>
239             { en => 'Parsing the eval string of length %s into classes.', },
240             debug_step_3 =>
241             { en => 'Parsed the eval string into %s number of classes.', },
242             debug_step_4 => {
243             en => 'Set the Module::Generate %s accessor with the value %s.'
244             },
245             debug_step_5 => { en => 'Start building macros' },
246             debug_step_6 => { en => 'Build macro' },
247             debug_step_7 => { en => 'Attempt to import %s macro object.' },
248             debug_step_8 => { en => 'Successfully imported %s macro object.', },
249             debug_step_9 =>
250             { en => 'Attempt to import %s macro from the hades file.' },
251             debug_step_10 =>
252             { en => 'Successfully imported %s macro from the hades file.' },
253             debug_step_11 => { en => 'Successfully built macros.' },
254             debug_step_12 => { en => 'Building Module::Generate class %s.' },
255             debug_step_13 => { en => 'Parsing class token.' },
256             debug_step_14 => { en => 'Setting last inheritance token: %s.' },
257             debug_step_14_b => { en => 'The last token was: %s.' },
258             debug_step_15 =>
259             { en => 'Call Module::Generate\'s %s method with the value %s.' },
260             debug_step_16 =>
261             { en => 'Build a accessor named %s with no arguments.' },
262             debug_step_17 => { en => 'Build the classes %s.' },
263             debug_step_18 => { en => 'Build a sub named %s with no arguments.' },
264             debug_step_19 =>
265             { en => 'Declare the classes global our variables', },
266             debug_step_20 => {
267             en => 'Found a group of attributes or subs so will iterrate each.'
268             },
269             debug_step_21 =>
270             { en => 'Building attributes for a sub or accessor named %s.' },
271             debug_step_22 => { en => 'Built attributes for %s.' },
272             debug_step_23 => { en => 'Constructing accessor named %s.' },
273             debug_step_24 => { en => 'Built private code for %s.' },
274             debug_step_25 => { en => 'Built coerce code for %s.' },
275             debug_step_26 => { en => 'Built type code for %s.' },
276             debug_step_27 => { en => 'Built trigger for %s.' },
277             debug_step_28 => { en => 'Constructed accessor named %s.' },
278             debug_step_29 => { en => 'Construct a modify sub routine named %s.' },
279             debug_step_30 =>
280             { en => 'Constructed a modify sub routine named %s.' },
281             debug_step_31 => { en => 'Construct a sub routine named %s.' },
282             debug_step_32 => { en => 'Constructed a sub routine named %s.' },
283             debug_step_33 =>
284             { en => 'Construct the new sub routine for class %s.' },
285             debug_step_34 =>
286             { en => 'Constructed the new sub routine for class %s.' },
287             debug_step_35 => { en => 'Finished Compiling the class.' },
288             debug_step_36 => { en => 'Finished Compiling all classes.' },
289             debug_step_37 => {
290             en =>
291             'Calling Module::Generates generate method which will write the files to disk.'
292             },
293             debug_step_38 => { en => 'Constructing code for %s.', },
294             debug_step_39 => { en => 'Build macro for: %s.' },
295             debug_step_40 => { en => 'Matched macro %s that has parameters.' },
296             debug_step_41 => { en => 'Macro %s has a code callback.' },
297             debug_step_42 => { en => 'Generated code for macro %s.' },
298             debug_step_43 => { en => 'Match macro %s that has no parameters.' },
299             debug_step_44 => { en => 'Constructed code for %s.', },
300             debug_step_45 => { en => 'Constructing predicate named has_%s.' },
301             debug_step_46 => { en => 'Constructed predicate named has_%s.' },
302             debug_step_47 => { en => 'Constructing clearer named clearer_%s.' },
303             debug_step_48 => { en => 'Constructed clearer named clearer_%s.' },
304             press_enter_to_continue => { en => 'Press enter to continue' },
305             };
306 37         161 return $steps;
307              
308             }
309              
310             sub DESTROY {
311 28     28   9895 my ($self) = @_;
312              
313             }
314              
315             sub AUTOLOAD {
316 0     0     my ($self) = @_;
317              
318 0           my ( $cls, $vn ) = ( ref $_[0], q{[^:'[:cntrl:]]{0,1024}} );
319 0           our $AUTOLOAD =~ /^${cls}::($vn)$/;
320 0 0         return $self->string($1) if $1;
321              
322             }
323              
324             1;
325              
326             __END__
327              
328             =head1 NAME
329              
330             Hades::Myths::Object - display text locally.
331              
332             =head1 VERSION
333              
334             Version 0.01
335              
336             =cut
337              
338             =head1 SYNOPSIS
339              
340             Quick summary of what the module does:
341              
342             use Hades::Myths::Object;
343              
344             my $locales = Hades::Myths::Object->new({
345             locale => 'ja_JP',
346             locales => {
347             stranger => {
348             en_GB => 'Hello stranger',
349             en_US => 'Howdy stranger',
350             ja_JP => 'こんにちは見知らぬ人'
351             },
352             }
353             });
354              
355             say $locales->stranger;
356              
357             =head1 SUBROUTINES/METHODS
358              
359             =head2 new
360              
361             Instantiate a new Hades::Myths::Object object.
362              
363             Hades::Myths::Object->new
364              
365             =head2 _build_locale
366              
367             call _build_locale method. Expects param $locale to be a Optional[Str].
368              
369             $obj->_build_locale($locale)
370              
371             =head2 _set_language_from_locale
372              
373             call _set_language_from_locale method. Expects param $value to be a Str.
374              
375             $obj->_set_language_from_locale($value)
376              
377             =head2 has_language
378              
379             has_language will return true if language accessor has a value.
380              
381             $obj->has_language
382              
383             =head2 _build_locales
384              
385             call _build_locales method. Expects param $values to be a HashRef.
386              
387             $obj->_build_locales($values)
388              
389             =head2 convert_locale
390              
391             Split a locale into locale and language.
392              
393             $obj->convert_locale($locale, $fb)
394              
395             =head2 add
396              
397             Add an item into the locales. This method expects a reference $key that should be a Str and a locales HashRef where the keys are locales and the values are the text string.
398              
399             locales->add('stranger', {
400             en_US => 'Howdy stranger!'
401             });
402            
403              
404             =head2 string
405              
406             call string method. Expects param $key to be a Str, param $locale to be a Str, param $lang to be a Str, param $fb to be a Str.
407              
408             $obj->string($key, $locale, $lang, $fb)
409              
410             =head2 debug_steps
411              
412             call debug_steps method. Expects param $steps to be any value including undef.
413              
414             $obj->debug_steps($steps)
415              
416             =head2 DESTROY
417              
418             call DESTROY method. Expects no params.
419              
420             $obj->DESTROY()
421              
422             =head2 AUTOLOAD
423              
424             call AUTOLOAD method. Expects no params.
425              
426             $obj->AUTOLOAD()
427              
428             =head1 ACCESSORS
429              
430             =head2 fb
431              
432             The fallback locale/language that is used when no value in the locales hash matches the objects locale or language. You can get or set this attribute and it expects a Str value. This attribute will default to be 'en'.
433              
434             $obj->fb;
435              
436             $obj->fb($value);
437              
438             =head2 locale
439              
440             The locale that will be checked for first when stringiying. You can get or set this attribute and it expects a Str value. This attribute will default to use Posix::setlocale
441              
442             $obj->locale;
443              
444             $obj->locale($value);
445              
446             =head2 language
447              
448             The language that will be checked for second when stringifying. You can get or set this attribute and it expects a Str value. This attribute will be defaulted to be the first part of a locale.
449              
450             $obj->language;
451              
452             $obj->language($value);
453              
454             =head2 locales
455              
456             The hash reference of strings that map to each locale.
457              
458             $obj->locales({
459             stranger => {
460             en_US => 'Howdy stranger!'
461             }
462             })
463            
464              
465             =head1 AUTHOR
466              
467             LNATION, C<< <email at lnation.org> >>
468              
469             =head1 BUGS
470              
471             Please report any bugs or feature requests to C<bug-hades::myths::object at rt.cpan.org>, or through
472             the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Hades-Myths-Object>. I will be notified, and then you'll
473             automatically be notified of progress on your bug as I make changes.
474              
475             =head1 SUPPORT
476              
477             You can find documentation for this module with the perldoc command.
478              
479             perldoc Hades::Myths::Object
480              
481             You can also look for information at:
482              
483             =over 4
484              
485             =item * RT: CPAN's request tracker (report bugs here)
486              
487             L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Hades-Myths-Object>
488              
489             =item * AnnoCPAN: Annotated CPAN documentation
490              
491             L<http://annocpan.org/dist/Hades-Myths-Object>
492              
493             =item * CPAN Ratings
494              
495             L<https://cpanratings.perl.org/d/Hades-Myths-Object>
496              
497             =item * Search CPAN
498              
499             L<https://metacpan.org/release/Hades-Myths-Object>
500              
501             =back
502              
503             =head1 ACKNOWLEDGEMENTS
504              
505             =head1 LICENSE AND COPYRIGHT
506              
507             This software is Copyright (c) 2020 by LNATION.
508              
509             This is free software, licensed under:
510              
511             The Artistic License 2.0 (GPL Compatible)
512              
513             =cut
514              
515