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   68285 use strict;
  15         42  
  15         478  
3 15     15   81 use warnings;
  15         34  
  15         479  
4 15     15   581 use POSIX qw/locale_h/;
  15         6541  
  15         118  
5             our $VERSION = 0.21;
6              
7             sub new {
8 42 100   42 1 42287 my ( $cls, %args ) = ( shift(), scalar @_ == 1 ? %{ $_[0] } : @_ );
  26         112  
9 42         113 my $self = bless {}, $cls;
10             my %accessors = (
11             locales => {
12             builder => sub {
13 41     41   101 my ( $self, $value ) = @_;
14 41         122 $value = $self->_build_locales($value);
15 39         156 return $value;
16             }
17             },
18             fb => { default => 'en', },
19             locale => {
20             builder => sub {
21 40     40   88 my ( $self, $value ) = @_;
22 40         145 $value = $self->_build_locale($value);
23 38         122 return $value;
24             }
25             },
26 42         408 language => {},
27             );
28 42         159 for my $accessor ( keys %accessors ) {
29             my $param
30             = defined $args{$accessor}
31             ? $args{$accessor}
32 158 100       388 : $accessors{$accessor}->{default};
33             my $value
34             = $self->$accessor( $accessors{$accessor}->{builder}
35 158 100       546 ? $accessors{$accessor}->{builder}->( $self, $param )
36             : $param );
37 149 50 33     449 unless ( !$accessors{$accessor}->{required} || defined $value ) {
38 0         0 die "$accessor accessor is required";
39             }
40             }
41 33         348 return $self;
42             }
43              
44             sub fb {
45 955     955 1 2727 my ( $self, $value ) = @_;
46 955 100       1670 if ( defined $value ) {
47 41 100       114 if ( ref $value ) {
48 4         46 die qq{Str: invalid value $value for accessor fb};
49             }
50 37         84 $self->{fb} = $value;
51             }
52 951         1796 return $self->{fb};
53             }
54              
55             sub locale {
56 954     954 1 2739 my ( $self, $value ) = @_;
57 954 100       1770 if ( defined $value ) {
58 41 100       96 if ( ref $value ) {
59 2         20 die qq{Str: invalid value $value for accessor locale};
60             }
61 39         97 $self->{locale} = $value;
62 39         125 $self->_set_language_from_locale($value);
63             }
64 952         2315 return $self->{locale};
65             }
66              
67             sub _build_locale {
68 42     42   679 my ( $self, $locale ) = @_;
69 42 100       108 if ( defined $locale ) {
70 26 100       85 if ( ref $locale ) {
71 4         44 die
72             qq{Optional[Str]: invalid value $locale for variable \$locale in method _build_locale};
73             }
74             }
75              
76 38   66     191 return $locale || setlocale(LC_CTYPE);
77              
78             }
79              
80             sub _set_language_from_locale {
81 42     42   1236 my ( $self, $value ) = @_;
82 42 100 100     253 if ( !defined($value) || ref $value ) {
83 3 100       10 $value = defined $value ? $value : 'undef';
84 3         29 die
85             qq{Str: invalid value $value for variable \$value in method _set_language_from_locale};
86             }
87              
88 39 100       110 unless ( $self->has_language ) {
89 27         85 my ( $locale, $lang ) = $self->convert_locale($value);
90 27 50       81 if ($lang) { $self->language($lang); }
  27         71  
91             }
92              
93             }
94              
95             sub language {
96 981     981 1 2340 my ( $self, $value ) = @_;
97 981 100       1726 if ( defined $value ) {
98 44 100       99 if ( ref $value ) {
99 2         19 die qq{Str: invalid value $value for accessor language};
100             }
101 42         118 $self->{language} = $value;
102             }
103 979         1743 return $self->{language};
104             }
105              
106             sub has_language {
107 41     41 1 81 my ($self) = @_;
108 41         148 return exists $self->{language};
109             }
110              
111             sub locales {
112 4658     4658 1 10419 my ( $self, $value ) = @_;
113 4658 100       7522 if ( defined $value ) {
114 45 100 100     162 if ( ( ref($value) || "" ) ne "HASH" ) {
115 2         20 die
116             qq{Map[Str, HashRef]: invalid value $value for accessor locales};
117             }
118 43         70 for my $key ( keys %{$value} ) {
  43         276  
119 1897         2386 my $val = $value->{$key};
120 1897 50       2874 if ( ref $key ) {
121 0         0 die
122             qq{Map[Str, HashRef]: invalid value $key for accessor locales expected Str};
123             }
124 1897 100 100     3902 if ( ( ref($val) || "" ) ne "HASH" ) {
125 6 100       14 $val = defined $val ? $val : 'undef';
126 6         66 die
127             qq{Map[Str, HashRef]: invalid value $val for accessor locales expected HashRef};
128             }
129             }
130 37         130 $self->{locales} = $value;
131             }
132 4650         18165 return $self->{locales};
133             }
134              
135             sub _build_locales {
136 43     43   818 my ( $self, $values ) = @_;
137 43 100       100 $values = defined $values ? $values : {};
138 43 100 100     207 if ( ( ref($values) || "" ) ne "HASH" ) {
139 4 50       11 $values = defined $values ? $values : 'undef';
140 4         42 die
141             qq{HashRef: invalid value $values for variable \$values in method _build_locales};
142             }
143              
144 39         98 my ($debug_steps) = debug_steps();
145             return {
146 39         92 %{$values}, %{$debug_steps},
  39         328  
147 39 50       72 ( $self->locales ? ( %{ $self->locales } ) : () )
  0         0  
148             };
149              
150             }
151              
152             sub convert_locale {
153 45     45 1 2409 my ( $self, $locale, $fb ) = @_;
154 45 100 66     212 if ( !defined($locale) || ref $locale ) {
155 2 50       8 $locale = defined $locale ? $locale : 'undef';
156 2         26 die
157             qq{Str: invalid value $locale for variable \$locale in method convert_locale};
158             }
159 43 100       119 $fb = defined $fb ? $fb : "en";
160 43 100 66     169 if ( !defined($fb) || ref $fb ) {
161 2 50       6 $fb = defined $fb ? $fb : 'undef';
162 2         22 die
163             qq{Str: invalid value $fb for variable \$fb in method convert_locale};
164             }
165              
166 41         215 $locale =~ m/^(\w\w)_(\w\w).*/;
167 41 50 33     343 return $1 && $2 ? ( $1 . '_' . $2, $1, $fb ) : ( $locale, $fb, $fb );
168              
169             }
170              
171             sub add {
172 7     7 1 4519 my ( $self, $key, $locales ) = @_;
173 7 100 66     42 if ( !defined($key) || ref $key ) {
174 2 50       7 $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     21 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         6 for my $key ( keys %{$locales} ) {
  3         10  
183 3         7 my $val = $locales->{$key};
184 3 50       7 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     15 if ( ( ref($val) || "" ) ne "HASH" ) {
189 3 100       8 $val = defined $val ? $val : 'undef';
190 3         29 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 6845 my ( $self, $key, $locale, $lang, $fb ) = @_;
201 920 100 66     3426 if ( !defined($key) || ref $key ) {
202 2 50       9 $key = defined $key ? $key : 'undef';
203 2         26 die qq{Str: invalid value $key for variable \$key in method string};
204             }
205 918 100       2277 $locale = defined $locale ? $locale : $self->locale;
206 918 100 66     2928 if ( !defined($locale) || ref $locale ) {
207 2 50       14 $locale = defined $locale ? $locale : 'undef';
208 2         19 die
209             qq{Str: invalid value $locale for variable \$locale in method string};
210             }
211 916 100       2114 $lang = defined $lang ? $lang : $self->language;
212 916 100 66     2791 if ( !defined($lang) || ref $lang ) {
213 2 50       6 $lang = defined $lang ? $lang : 'undef';
214 2         20 die qq{Str: invalid value $lang for variable \$lang in method string};
215             }
216 914 100       2165 $fb = defined $fb ? $fb : $self->fb;
217 914 100 66     2829 if ( !defined($fb) || ref $fb ) {
218 2 50       5 $fb = defined $fb ? $fb : 'undef';
219 2         19 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     1670 || !scalar keys %{ $self->locales->{$key} } );
  912         1523  
225             $_ && exists $self->locales->{$key}->{$_}
226             and return $self->locales->{$key}->{$_}
227 912   66     2785 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 39     39 1 74 my ( $self, $steps ) = @_;
235              
236 39         1972 $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 39         174 return $steps;
307              
308             }
309              
310             sub DESTROY {
311 28     28   10206 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