File Coverage

blib/lib/Rose/HTML/Object/MakeMethods/Localization.pm
Criterion Covered Total %
statement 170 261 65.1
branch 60 132 45.4
condition 31 99 31.3
subroutine 18 21 85.7
pod 0 4 0.0
total 279 517 53.9


line stmt bran cond sub pod time code
1             package Rose::HTML::Object::MakeMethods::Localization;
2              
3 43     43   354 use strict;
  43         106  
  43         1261  
4              
5 43     43   220 use Carp();
  43         105  
  43         803  
6              
7 43     43   203 use base 'Rose::Object::MakeMethods';
  43         405  
  43         155565  
8              
9             our $VERSION = '0.615';
10              
11             sub localized_message
12             {
13 153     153 0 12522 my($class, $name, $args, $opts) = @_;
14              
15 153         297 my %methods;
16              
17 153   50     769 my $interface = $args->{'interface'} || 'get_set';
18 153   33     613 my $key = $args->{'hash_key'} || $name;
19 153   33     727 my $id_method = $args->{'msg_id_method'} || $key . '_message_id';
20              
21 153   50     608 my $accept_msg_class = $args->{'accept_msg_class'} || 'Rose::HTML::Object::Message';
22              
23 153         24969 require Rose::HTML::Object::Message::Localized;
24              
25 153 50       1803 if($interface eq 'get_set')
26             {
27             $methods{$name} = sub
28             {
29 2204     2204   10810 my($self) = shift;
30              
31 2204 100       5261 if(@_)
32             {
33 852 50       2180 if(@_ > 1)
34             {
35 0         0 my($id) = shift;
36              
37 0         0 my @args;
38              
39 0 0 0     0 if(@_ == 1 && ref($_[0]) =~ /^(?:HASH|ARRAY)$/)
40             {
41 0         0 @args = (args => $_[0]);
42             }
43             else
44             {
45 0         0 @args = (args => [ @_ ]);
46             }
47              
48 0 0       0 unless($id =~ /^\d+$/)
49             {
50 0   0     0 $id = $self->localizer->get_message_id($id) ||
51             Carp::croak "Unknown message id: '$id'";
52             }
53              
54 0         0 return $self->$name($self->localizer->message_class->new(id => $id, parent => $self, @args));
55             }
56              
57 852         1532 my $msg = shift;
58              
59 852 100       3529 if(UNIVERSAL::isa($msg, $accept_msg_class))
60             {
61 483         1622 $msg->parent($self);
62 483         2423 return $self->{$key} = $msg;
63             }
64             else
65             {
66 369         1464 return $self->{$key} = $self->localizer->message_class->new(text => $msg, parent => $self);
67             }
68             }
69              
70 1352         5292 return $self->{$key};
71 153         1211 };
72              
73             $methods{$id_method} = sub
74             {
75 363     363   1389 my($self) = shift;
76              
77 363 50       875 if(@_)
78             {
79 363         756 my($id, @args) = @_;
80 363 100       899 return $self->$name(undef) unless(defined $id);
81 349         1143 return $self->$name($self->localizer->message_class->new(id => $id, args => \@args, parent => $self));
82             }
83              
84 0         0 my $error = $self->$name();
85 0 0       0 return $error->id if(UNIVERSAL::can($error, 'id'));
86 0         0 return undef;
87 153         1035 };
88             }
89 0         0 else { Carp::croak "Unknown interface: $interface" }
90              
91 153         600 return \%methods;
92             }
93              
94             sub localized_error
95             {
96 0     0 0 0 my($class, $name, $args) = @_;
97              
98 0         0 my %methods;
99              
100 0   0     0 my $interface = $args->{'interface'} || 'get_set';
101 0   0     0 my $key = $args->{'hash_key'} || $name;
102 0   0     0 my $id_method = $args->{'error_id_method'} || $key . '_id';
103              
104 0   0     0 my $accept_error_class = $args->{'accept_error_class'} || 'Rose::HTML::Object::Error';
105              
106 0         0 require Rose::HTML::Object::Error;
107              
108 0 0       0 if($interface eq 'get_set')
109             {
110             $methods{$name} = sub
111             {
112 0     0   0 my($self) = shift;
113              
114 0 0       0 if(@_)
115             {
116 0 0       0 return $self->{$key} = undef unless(defined $_[0]);
117              
118 0         0 my $localizer = $self->localizer;
119              
120 0 0       0 if(@_ > 1)
121             {
122 0         0 my($id) = shift;
123              
124 0         0 my @args;
125              
126 0 0 0     0 if(@_ == 1 && ref($_[0]) =~ /^(?:HASH|ARRAY)$/)
127             {
128 0         0 @args = (args => $_[0]);
129             }
130             else
131             {
132 0         0 @args = (args => [ @_ ]);
133             }
134              
135 0 0       0 unless($id =~ /^\d+$/)
136             {
137 0   0     0 $id = $self->localizer->get_error_id($id) ||
138             Carp::croak "Attempt to call $name() with more than one ",
139             "argument, and the first argument is not a numeric ",
140             "error id: '$id'";
141             }
142              
143 0         0 unshift(@args, error_id => $id);
144              
145 0         0 my $message;
146              
147 0 0       0 if($self->can('message_for_error_id'))
148             {
149 0         0 $message = $self->message_for_error_id(@args);
150              
151 0 0       0 unless(defined $message)
152             {
153 0         0 $message = $localizer->message_for_error_id(@args);
154             }
155             }
156             else
157             {
158 0         0 $message = $localizer->message_for_error_id(@args);
159             }
160              
161              
162 0         0 return $self->$name($localizer->error_class->new(id => $id,
163             parent => $self,
164             message => $message));
165             }
166              
167 0         0 my $error = shift;
168              
169 0 0       0 if(UNIVERSAL::isa($error, $accept_error_class))
    0          
170             {
171 0         0 $error->parent($self);
172 0         0 return $self->{$key} = $error;
173             }
174             elsif(defined $error)
175             {
176 0         0 return $self->{$key} =
177             $localizer->error_class->new(message => $localizer->messsage_class->new($error),
178             parent => $self);
179             }
180             }
181              
182 0         0 return $self->{$key};
183 0         0 };
184              
185             $methods{$id_method} = sub
186             {
187 0     0   0 my($self) = shift;
188              
189 0 0       0 if(@_)
190             {
191 0         0 my($id) = shift;
192              
193 0         0 my $localizer = $self->localizer;
194              
195 0         0 my @args;
196              
197 0 0 0     0 if(@_ == 1 && ref($_[0]) =~ /^(?:HASH|ARRAY)$/)
198             {
199 0         0 @args = (args => $_[0]);
200             }
201             else
202             {
203 0         0 @args = (args => [ @_ ]);
204             }
205              
206 0 0       0 unless($id =~ /^\d+$/)
207             {
208 0   0     0 $id = $localizer->get_error_id($id) ||
209             Carp::croak "Unknown error id: '$id'";
210             }
211              
212 0         0 unshift(@args, error_id => $id);
213              
214 0         0 my $message;
215              
216 0 0       0 if($self->can('message_for_error_id'))
217             {
218 0         0 $message = $self->message_for_error_id(@args);
219              
220 0 0       0 unless(defined $message)
221             {
222 0         0 $message = $localizer->message_for_error_id(@args);
223             }
224             }
225             else
226             {
227 0         0 $message = $localizer->message_for_error_id(@args);
228             }
229              
230              
231 0         0 return $self->$name($localizer->error_class->new(id => $id,
232             parent => $self,
233             message => $message));
234             }
235              
236 0         0 my $error = $self->$name();
237 0 0       0 return $error->id if(UNIVERSAL::can($error, 'id'));
238 0         0 return undef;
239 0         0 };
240              
241             }
242 0         0 else { Carp::croak "Unknown interface: $interface" }
243              
244 0         0 return \%methods;
245             }
246              
247             sub localized_errors
248             {
249 43     43 0 5830 my($class, $name, $args) = @_;
250              
251 43         103 my %methods;
252              
253 43   50     348 my $interface = $args->{'interface'} || 'get_set';
254 43   33     268 my $key = $args->{'hash_key'} || $name;
255 43   33     201 my $plural_name = $args->{'plural_name'} || $name;
256 43   33     194 my $singular_name = $args->{'singular_name'} || plural_to_singular($plural_name);
257 43   33     306 my $has_method = $args->{'has_error_method'} || 'has_' . $plural_name;
258 43   33     253 my $has_method2 = $args->{'has_errors_method'} || 'has_' . $singular_name;
259 43   33     245 my $add_method = $args->{'add_error_method'} || 'add_' . $singular_name;
260 43   33     241 my $adds_method = $args->{'add_errors_method'} || 'add_' . $plural_name;
261 43   33     590 my $id_method = $args->{'error_id_method'} || $singular_name . '_id';
262 43   33     228 my $ids_method = $args->{'error_ids_method'} || $singular_name . '_ids';
263 43   33     222 my $add_id_method = $args->{'add_error_id_method'} || 'add_' . $singular_name . '_id';
264 43   33     201 my $add_ids_method = $args->{'add_error_ids_method'} || 'add_' . $singular_name . '_ids';
265              
266 43   50     253 my $accept_error_class = $args->{'accept_error_class'} || 'Rose::HTML::Object::Error';
267              
268 43         19606 require Rose::HTML::Object::Error;
269              
270 43 50       235 if($interface eq 'get_set')
271             {
272             $methods{$plural_name} = sub
273             {
274 19     19   70 my($self) = shift;
275              
276 19 100       47 if(@_)
277             {
278 8 100 66     44 if(!defined $_[0] || (ref $_[0] eq 'ARRAY' && !@{$_[0]}))
  1   100     6  
279             {
280 2         10 return $self->{$key} = undef;
281             }
282              
283 6         23 $self->{$key} = undef;
284 6         31 $self->$adds_method(@_);
285             }
286              
287 17 50       54 return wantarray ? @{$self->{$key} || []} : $self->{$key};
  11 100       72  
288 43         1472 };
289              
290             $methods{$singular_name} = sub
291             {
292 6423     6423   22413 my($self) = shift;
293              
294 6423 100       13533 if(@_)
295             {
296 4442 100       12540 return $self->{$key} = undef unless(defined $_[0]);
297              
298 20         120 my $localizer = $self->localizer;
299              
300 20 100       718 if(@_ > 1)
301             {
302 2         6 my($id) = shift;
303              
304 2         5 my @args;
305              
306 2 50 33     18 if(@_ == 1 && ref($_[0]) =~ /^(?:HASH|ARRAY)$/)
307             {
308 2         8 @args = (args => $_[0]);
309             }
310             else
311             {
312 0         0 @args = (args => [ @_ ]);
313             }
314              
315 2 50       10 unless($id =~ /^\d+$/)
316             {
317 0   0     0 $id = $localizer->get_error_id($id) ||
318             Carp::croak "Attempt to call $singular_name() with more than one ",
319             "argument, and the first argument is not a numeric ",
320             "error id: '$id'";
321             }
322              
323 2         6 unshift(@args, error_id => $id);
324              
325 2         4 my $message;
326              
327 2 50       12 if($self->can('message_for_error_id'))
328             {
329 2         7 $message = $self->message_for_error_id(@args);
330              
331 2 50       6 unless(defined $message)
332             {
333 2         9 $message = $localizer->message_for_error_id(@args);
334             }
335             }
336             else
337             {
338 0         0 $message = $localizer->message_for_error_id(@args);
339             }
340              
341 2         18 $self->{$key} =
342             [ $localizer->error_class->new(id => $id, parent => $self, message => $message) ];
343              
344 2         29 return $self->{$key}[-1];
345             }
346              
347 18         57 my $error = shift;
348              
349 18 50       194 if(UNIVERSAL::isa($error, $accept_error_class))
    50          
350             {
351 0         0 $error->parent($self);
352 0         0 $self->{$key} = [ $error ];
353             }
354             elsif(defined $error)
355             {
356 18         106 $self->{$key} =
357             [ $localizer->error_class->new(message => $localizer->message_class->new($error), parent => $self) ];
358             }
359             }
360              
361 1999         8495 return $self->{$key}[-1];
362 43         260 };
363              
364             $methods{$adds_method} = sub
365             {
366 7     7   19 my($self) = shift;
367              
368 7 50       31 return unless(@_);
369              
370 7         29 my $localizer = $self->localizer;
371 7         153 my $errors = __errors_from_args($self, \@_, $localizer->error_class, $localizer->message_class, $accept_error_class, 0, 0);
372              
373 7         17 push(@{$self->{$key}}, @$errors);
  7         23  
374              
375 7 50       28 return wantarray ? @$errors : $errors;
376 43         183 };
377              
378             $methods{$add_method} = sub
379             {
380 5     5   14 my($self) = shift;
381              
382 5 50       18 return unless(@_);
383              
384 5         18 my $localizer = $self->localizer;
385 5         117 my $errors = __errors_from_args($self, \@_, $localizer->error_class, $localizer->message_class, $accept_error_class, 0, 1);
386              
387 5         14 push(@{$self->{$key}}, @$errors);
  5         14  
388              
389 5 50       21 return wantarray ? @$errors : $errors;
390 43         196 };
391              
392             $methods{$id_method} = sub
393             {
394 43     43   211 my($self) = shift;
395              
396 43 100       140 if(@_)
397             {
398 32         142 my $localizer = $self->localizer;
399 32         1109 my $errors = __errors_from_args($self, \@_, $localizer->error_class, $localizer->message_class, $accept_error_class, 1, 1);
400 32         121 $self->{$key} = $errors;
401 32         118 return $errors->[-1]->id;
402             }
403              
404 11 50       56 return $self->{$key}[-1] ? $self->{$key}[-1]->id : undef;
405 43         1270 };
406              
407             $methods{$ids_method} = sub
408             {
409 1     1   3 my($self) = shift;
410              
411 1 50       5 if(@_)
412             {
413 0         0 my $localizer = $self->localizer;
414 0         0 my $errors = __errors_from_args($self, \@_, $localizer->error_class, $localizer->message_class, $accept_error_class, 1, 0);
415 0         0 $self->{$key} = $errors;
416 0 0       0 return wantarray ? @$errors : $errors;
417             }
418              
419 1 50       4 if(defined(my $want = wantarray))
420             {
421 1 50       2 my @ids = map { $_->id } @{$self->{$key} || []};
  2         7  
  1         5  
422 1 50       9 return $want ? @ids : \@ids;
423             }
424              
425 0         0 return;
426 43         202 };
427              
428             $methods{$add_ids_method} = sub
429             {
430 1     1   3 my($self) = shift;
431              
432 1 50       4 return unless(@_);
433              
434 1         4 my $localizer = $self->localizer;
435 1         11 my $errors = __errors_from_args($self, \@_, $localizer->error_class, $localizer->message_class, $accept_error_class, 1, 1);
436              
437 1         3 push(@{$self->{$key}}, @$errors);
  1         3  
438              
439 1 50       5 if(defined(my $want = wantarray))
440             {
441 0         0 my @ids = map { $_->id } @$errors;
  0         0  
442 0 0       0 return $want ? @ids : \@ids;
443             }
444              
445 1         3 return;
446 43         185 };
447              
448             $methods{$add_id_method} = sub
449             {
450 68     68   174 my($self) = shift;
451              
452 68 50       247 return unless(@_);
453              
454 68         307 my $localizer = $self->localizer;
455 68         2710 my $errors = __errors_from_args($self, \@_, $localizer->error_class, $localizer->message_class, $accept_error_class, 1, 0);
456              
457 68         168 push(@{$self->{$key}}, @$errors);
  68         256  
458              
459 68 50       243 if(defined(my $want = wantarray))
460             {
461 0         0 my @ids = map { $_->id } @$errors;
  0         0  
462 0 0       0 return $want ? @ids : \@ids;
463             }
464              
465 68         234 return;
466 43         2441 };
467              
468 43 100   38   240 $methods{$has_method} = sub { scalar @{shift->{$key} || []} };
  38         854  
  38         365  
469 43         127 $methods{$has_method2} = $methods{$has_method};
470             }
471 0         0 else { Carp::croak "Unknown interface: $interface" }
472              
473 43         229 return \%methods;
474             }
475              
476             sub plural_to_singular
477             {
478 43     43 0 93 my($word) = shift;
479 43 50       297 return $word if($word =~ /[aeiouy]ss$/i);
480 43         203 $word =~ s/s$//;
481 43         217 return $word;
482             }
483              
484             # Acceptable formats:
485             #
486             # <error object>, ...
487             # <numeric error id> (id method only)
488             # <list of numeric error ids> (non-singular id method only)
489             # <numeric error id> <list of args> (singular only)
490             # <numeric error id> <arrayref of args>, ...
491             # <numeric error id> <hashref of args>, ...
492             sub __errors_from_args
493             {
494 113     113   1455 my($self, $args, $error_class, $msg_class, $accept_error_class, $id_method, $singular) = @_;
495              
496 113         269 local $Carp::CarpLevel = 1;
497              
498 113 50 66     559 $args = $args->[0] if(@$args == 1 && ref($args->[0]) eq 'ARRAY');
499              
500 113         223 my @errors;
501              
502 113         351 my $localizer = $self->localizer;
503              
504 113         3255 for(my $i = 0; $i <= $#$args; $i++)
505             {
506 119         309 my $arg = $args->[$i];
507              
508 119 100       533 if(UNIVERSAL::isa($arg, $accept_error_class))
509             {
510 5         25 $arg->parent($self);
511 5         12 push(@errors, $arg);
512 5         13 next;
513             }
514              
515 114         228 my $id = $arg;
516              
517 114 100 100     978 if($id_method && $id !~ /^\d+$/)
518             {
519 3   33     19 $id = $localizer->get_error_id($id) ||
520             Carp::croak "Unknown error id: '$id'";
521             }
522              
523 114         275 my @msg_args;
524              
525 114 100 66     762 if(ref($args->[$i + 1]) =~ /^(?:HASH|ARRAY)$/)
    50          
526             {
527 57         229 @msg_args = (args => $args->[++$i]);
528             }
529             elsif($singular && ($i + 1) < $#$args)
530             {
531 0         0 @msg_args = (args => [ @$args[$i + 1 .. $#$args] ]);
532 0         0 $i = $#$args;
533             }
534              
535 114         502 unshift(@msg_args, error_id => $id, msg_class => $msg_class);
536              
537 114         224 my $message;
538              
539 114 100       550 if($id =~ /^\d+$/)
540             {
541 105 50       490 if($self->can('message_for_error_id'))
542             {
543 105         448 $message = $self->message_for_error_id(@msg_args);
544              
545 105 100       366 unless(defined $message)
546             {
547 68         304 $message = $localizer->message_for_error_id(@msg_args);
548             }
549             }
550             else
551             {
552 0         0 $message = $localizer->message_for_error_id(@msg_args);
553             }
554              
555 105         941 push(@errors, $error_class->new(id => $id,
556             message => $message,
557             parent => $self));
558             }
559             else
560             {
561 9         31 push(@errors, $error_class->new(message => $msg_class->new($id),
562             parent => $self));
563             }
564             }
565              
566 113         962 return \@errors;
567             }
568              
569             1;