1 package WebPAC::Common;
6 use Log::Log4perl qw(get_logger :levels);
10 WebPAC::Common - internal methods called from other WebPAC modules
18 our $VERSION = '0.01';
20 #my $LOOKUP_REGEX = '\[[^\[\]]+\]';
21 #my $LOOKUP_REGEX_SAVE = '\[([^\[\]]+)\]';
22 my $LOOKUP_REGEX = 'lookup{[^\{\}]+}';
23 my $LOOKUP_REGEX_SAVE = 'lookup{([^\{\}]+)}';
27 This module defines common functions, and is used as base for other, more
30 my $webpac = new WebPAC::Common(
32 'filter_name_1' => sub {
43 Workhourse of all: takes record from in-memory structure of database and
44 strings with placeholders and returns string or array of with substituted
47 my $text = $webpac->fill_in($rec,'v250^a');
49 Optional argument is ordinal number for repeatable fields. By default,
50 it's assume to be first repeatable field (fields are perl array, so first
52 Following example will read second value from repeatable field.
54 my $text = $webpac->fill_in($rec,'Title: v250^a',1);
56 This function B<does not> perform parsing of format to inteligenty skip
57 delimiters before fields which aren't used.
59 This method will automatically decode UTF-8 string to local code page
67 my $log = $self->_get_logger();
69 my $rec = shift || $log->logconfess("need data record");
70 my $format = shift || $log->logconfess("need format to parse");
71 # iteration (for repeatable fields)
74 $log->logdie("infitite loop in format $format") if ($i > ($self->{'max_mfn'} || 9999));
76 # FIXME remove for speedup?
77 $log->logconfess("need HASH as first argument!") if ($rec !~ /HASH/o);
79 if (utf8::is_utf8($format)) {
80 $format = $self->_x($format);
86 # remove eval{...} from beginning
87 $eval_code = $1 if ($format =~ s/^eval{([^}]+)}//s);
90 # remove filter{...} from beginning
91 $filter_name = $1 if ($format =~ s/^filter{([^}]+)}//s);
93 # do actual replacement of placeholders
95 $format =~ s/v(\d+)(?:\^(\w))?/$self->get_data(\$rec,$1,$2,$i,\$found)/ges;
96 # non-repeatable fields
97 $format =~ s/s(\d+)(?:\^(\w))?/$self->get_data(\$rec,$1,$2,0,\$found)/ges;
100 $log->debug("format: $format");
102 my $eval = $self->fill_in($rec,$eval_code,$i);
103 return if (! $self->_eval($eval));
105 if ($filter_name && $self->{'filter'}->{$filter_name}) {
106 $log->debug("filter '$filter_name' for $format");
107 $format = $self->{'filter'}->{$filter_name}->($format);
108 return unless(defined($format));
109 $log->debug("filter result: $format");
111 # do we have lookups?
112 if ($format =~ /$LOOKUP_REGEX/o) {
113 $log->debug("format '$format' has lookup");
114 return $self->lookup($format);
126 Returns value from record.
128 my $text = $self->get_data(\$rec,$f,$sf,$i,\$found);
131 record reference C<$rec>,
133 optional subfiled C<$sf>,
134 index for repeatable values C<$i>.
136 Optinal variable C<$found> will be incremeted if there
139 Returns value or empty string.
146 my ($rec,$f,$sf,$i,$found) = @_;
149 return '' if (! $$rec->{$f}->[$i]);
151 if ($sf && $$rec->{$f}->[$i]->{$sf}) {
152 $$found++ if (defined($$found));
153 return $$rec->{$f}->[$i]->{$sf};
154 } elsif ($$rec->{$f}->[$i]) {
155 $$found++ if (defined($$found));
156 # it still might have subfield, just
157 # not specified, so we'll dump all
158 if ($$rec->{$f}->[$i] =~ /HASH/o) {
160 foreach my $k (keys %{$$rec->{$f}->[$i]}) {
161 $out .= $$rec->{$f}->[$i]->{$k}." ";
165 return $$rec->{$f}->[$i];
174 =head1 INTERNAL METHODS
176 Here is a quick list of internal methods, mostly useful to turn debugging
177 on them (see L<LOGGING> below for explanation).
183 Internal function to eval code without C<strict 'subs'>.
190 my $code = shift || return;
192 my $log = $self->_get_logger();
195 my $ret = eval $code;
197 $log->error("problem with eval code [$code]: $@");
200 $log->debug("eval: ",$code," [",$ret,"]");
202 return $ret || undef;
205 =head2 _sort_by_order
207 Sort xml tags data structure accoding to C<order=""> attribute.
214 my $va = $self->{'import_xml'}->{'indexer'}->{$a}->{'order'} ||
215 $self->{'import_xml'}->{'indexer'}->{$a};
216 my $vb = $self->{'import_xml'}->{'indexer'}->{$b}->{'order'} ||
217 $self->{'import_xml'}->{'indexer'}->{$b};
224 Convert string from UTF-8 to code page defined in C<import_xml>.
226 my $text = $webpac->_x('utf8 text');
228 Default application code page is C<ISO-8859-2>. You will probably want to
229 change that when creating new instance of object based on this one.
235 my $utf8 = shift || return;
237 # create UTF-8 convertor for import_xml files
238 $self->{'utf2cp'} ||= Text::Iconv->new('UTF-8' ,$self->{'code_page'} || 'ISO-8859-2');
240 return $self->{'utf2cp'}->convert($utf8) ||
241 $self->_get_logger()->logwarn("can't convert '$utf8'");
246 This function will init C<Log::Log4perl> using provided configuration file.
248 $webpac->_init_logger('/path/to/log.conf');
250 If no path to configuration file is given, dummy empty configuration
259 Log::Log4perl->init($file);
262 Log::Log4perl->init( \$conf );
269 Get C<Log::Log4perl> object with a twist: domains are defined for each
272 my $log = $webpac->_get_logger();
279 $self->{'_logger_ok'} ||= $self->_init_logger;
281 my $name = (caller(1))[3] || caller;
282 return get_logger($name);
288 Logging in WebPAC is performed by L<Log::Log4perl> with config file
291 Methods defined above have different levels of logging, so
292 it's descriptions will be useful to turn (mostry B<debug> logging) on
293 or off to see why WabPAC isn't perforing as you expect it (it might even
296 B<This is different from normal Log4perl behaviour>. To repeat, you can
297 also use method names, and not only classes (which are just few)