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