376
|
1 package IMPL::Web::Resources::StringMap;
|
|
2 use strict;
|
|
3
|
|
4 use IMPL::Const qw(:prop);
|
|
5 use IMPL::declare {
|
|
6 require => {
|
|
7 Exception => 'IMPL::Exception',
|
|
8 IOException => '-IMPL::IOException',
|
|
9 ArgException => '-IMPL::InvalidArgumentException'
|
|
10 },
|
|
11 props => [
|
|
12 _data => PROP_RW,
|
|
13 _parent => PROP_RW
|
|
14 ]
|
|
15 };
|
|
16
|
|
17 sub CTOR {
|
|
18 my ($this,$data,$parent) = @_;
|
|
19
|
|
20 die ArgException->new( data => 'A hash reference is required' )
|
|
21 unless ref($data) eq 'HASH';
|
|
22
|
|
23 die ArgException->new( data => 'A hash must contain either scalars or subs')
|
|
24 if grep not($_) || (ref($_) and ref($_) ne 'CODE'), values %$data;
|
|
25
|
|
26 $this->_data($data);
|
|
27 $this->_parent($parent);
|
|
28 }
|
|
29
|
|
30 sub GetString {
|
|
31 my ($this,$id,$args) = @_;
|
|
32
|
|
33 if(my $format = $this->_data->{$id}) {
|
|
34 return $this->FormatString($format,$args);
|
|
35 } else {
|
|
36 return $this->_parent? $this->_parent->GetString($id,$args) : "[$id]";
|
|
37 }
|
|
38
|
|
39 }
|
|
40
|
|
41 sub FormatString {
|
|
42 my ($self,$text,$args) = @_;
|
|
43
|
|
44 $args ||= {};
|
|
45 $resolver ||= \&_defaultResolver;
|
|
46 $text ||= '';
|
|
47
|
|
48 $string =~ s/%(\w+(?:\.\w+)*)%/$self->GetValue($args,$1,"\[$1\]")/ge;
|
|
49
|
|
50 return $string;
|
|
51
|
|
52 }
|
|
53
|
|
54 sub GetValue {
|
|
55 my ($self,$obj,$path,$default) = @_;
|
|
56
|
|
57 foreach my $chunk (split /\./,$path) {
|
|
58 return $default unless $obj;
|
|
59 if (ref $obj eq 'HASH') {
|
|
60 $obj = $obj->{$chunk};
|
|
61 } else {
|
|
62 $obj = $self->Resolve($obj,$chunk);
|
|
63 }
|
|
64 }
|
|
65 return $obj||'<undef>';
|
|
66 }
|
|
67
|
|
68 sub Resolve {
|
|
69 my ($self,$obj,$prop) = @_;
|
|
70
|
|
71 return ( eval { $obj->can($prop) } ? $obj->$prop() : undef );
|
|
72 }
|
|
73
|
|
74 sub _LoadMap {
|
|
75 my ($self,$file,$parent) = @_;
|
|
76
|
|
77 my $data = do $file;
|
|
78 my $e = $@;
|
|
79 die Exception->new("Failed to load file '$file'", $e) if $e;
|
|
80 die IOException->new("Failed to load file '$file'", $!) if not defined $data and $!;
|
|
81 die Exception->new("Failed to load file '$file'", "A hash data is expected") unless ref($data) eq 'HASH';
|
|
82
|
|
83 return $self->new($data,$parent);
|
|
84 }
|
|
85
|
|
86 1;
|
|
87
|
|
88 __END__
|
|
89
|
|
90 =pod
|
|
91
|
|
92 =head1 NAME
|
|
93
|
|
94 C<IMPL::Web::Resources::StringMap>
|
|
95
|
|
96 =head1 SYNOPSIS
|
|
97
|
|
98 My/App/locale/default/Search.labels
|
|
99
|
|
100 My/App/locale/en/Search.map
|
|
101
|
|
102 =begin code
|
|
103
|
|
104 {
|
|
105 TitleLabel => 'Search results',
|
|
106 ViewLabel => 'View %name%', # same as sub { $_[0]->Format('View %name%',$_[1]) }
|
|
107 ResultsCountLabel => sub {
|
|
108 my ($self,$args) = @_;
|
|
109
|
|
110 $args ||= {};
|
|
111
|
|
112 if (not $args->{count}) {
|
|
113 return "No items found";
|
|
114 } elsif($args->{count} == 1) {
|
|
115 return "Found one item";
|
|
116 } else {
|
|
117 return $self->Format("Found %count% items", $args);
|
|
118 }
|
|
119 }
|
|
120 }
|
|
121
|
|
122 =end code
|
|
123
|
|
124 =head1 DESCRIPTION
|
|
125
|
|
126 =head
|
|
127
|
|
128 =cut |