File Coverage

blib/lib/Log/Report/Extract.pm
Criterion Covered Total %
statement 68 102 66.6
branch 14 44 31.8
condition 5 27 18.5
subroutine 16 20 80.0
pod 11 12 91.6
total 114 205 55.6


line stmt bran cond sub pod time code
1             # This code is part of Perl distribution Log-Report-Lexicon version 1.15.
2             # The POD got stripped from this file by OODoc version 3.05.
3             # For contributors see file ChangeLog.
4              
5             # This software is copyright (c) 2007-2025 by Mark Overmeer.
6              
7             # This is free software; you can redistribute it and/or modify it under
8             # the same terms as the Perl 5 programming language system itself.
9             # SPDX-License-Identifier: Artistic-1.0-Perl OR GPL-1.0-or-later
10              
11             #oodist: *** DO NOT USE THIS VERSION FOR PRODUCTION ***
12             #oodist: This file contains OODoc-style documentation which will get stripped
13             #oodist: during its release in the distribution. You can use this file for
14             #oodist: testing, however the code of this development version may be broken!
15              
16             package Log::Report::Extract;{
17             our $VERSION = '1.15';
18             }
19              
20              
21 2     2   453089 use warnings;
  2         12  
  2         120  
22 2     2   31 use strict;
  2         4  
  2         55  
23              
24 2     2   9 use Log::Report 'log-report-lexicon';
  2         3  
  2         12  
25 2     2   5754 use Log::Report::Lexicon::Index ();
  2         5  
  2         73  
26 2     2   444 use Log::Report::Lexicon::POT ();
  2         6  
  2         3335  
27              
28             #--------------------
29              
30             sub new(@)
31 1     1 1 201471 { my $class = shift;
32 1         12 (bless {}, $class)->init( {@_} );
33             }
34              
35             sub init($)
36 1     1 0 3 { my ($self, $args) = @_;
37             my $lexi = $args->{lexicon} || $args->{lexicons}
38 1 50 33     9 or error __"extractions require an explicit lexicon directory";
39              
40 1 50 33     15 -d $lexi or mkdir $lexi
41             or fault __x"cannot create lexicon directory {dir}", dir => $lexi;
42              
43 1         10 $self->{LRE_index} = Log::Report::Lexicon::Index->new($lexi);
44 1   50     10 $self->{LRE_charset} = $args->{LRE_charset} || 'utf-8';
45 1         3 $self->{LRE_domains} = {};
46 1         3 $self;
47             }
48              
49             #--------------------
50              
51 2     2 1 15 sub index() { $_[0]->{LRE_index} }
52 1     1 1 3 sub charset() { $_[0]->{LRE_charset} }
53 2     2 1 5 sub domains() {sort keys %{ $_[0]->{LRE_domains}} }
  2         17  
54              
55              
56             sub pots($)
57 12     12 1 24 { my ($self, $domain) = @_;
58 12         26 my $r = $self->{LRE_domains}{$domain};
59 12 50       38 $r ? @$r : ();
60             }
61              
62              
63             sub addPot($$%)
64 0     0 1 0 { my ($self, $domain, $pot) = @_;
65 0 0       0 push @{$self->{LRE_domains}{$domain}}, ref $pot eq 'ARRAY' ? @$pot : $pot
  0 0       0  
66             if $pot;
67             }
68              
69             #--------------------
70              
71             sub process($@)
72 0     0 1 0 { my ($self, $fn, %opts) = @_;
73 0         0 panic "not implemented";
74             }
75              
76              
77             sub cleanup(%)
78 0     0 1 0 { my ($self, %args) = @_;
79 0   0     0 my $keep = $args{keep} || {};
80 0 0       0 $keep = +{ map +($_ => 1), @$keep }
81             if ref $keep eq 'ARRAY';
82              
83 0         0 foreach my $domain ($self->domains)
84 0         0 { $_->keepReferencesTo($keep) for $self->pots($domain);
85             }
86             }
87              
88              
89             sub showStats(;$)
90 0     0 1 0 { my $self = shift;
91 0 0       0 my @domains = @_ ? @_ : $self->domains;
92              
93 0 0       0 dispatcher needs => 'INFO'
94             or return;
95              
96 0         0 foreach my $domain (@domains)
97 0 0       0 { my $pots = $self->{LRE_domains}{$domain} or next;
98 0         0 my ($msgids, $fuzzy, $inactive) = (0, 0, 0);
99              
100 0         0 foreach my $pot (@$pots)
101 0         0 { my $stats = $pot->stats;
102 0 0 0     0 next unless $stats->{fuzzy} || $stats->{inactive};
103              
104 0         0 $msgids = $stats->{msgids};
105 0 0       0 next if $msgids == $stats->{fuzzy}; # ignore the template
106              
107             notice __x"{domain}: {fuzzy%3d} fuzzy, {inact%3d} inactive in {filename}",
108 0         0 domain => $domain, fuzzy => $stats->{fuzzy}, inact => $stats->{inactive}, filename => $pot->filename;
109              
110 0         0 $fuzzy += $stats->{fuzzy};
111 0         0 $inactive += $stats->{inactive};
112             }
113              
114 0 0 0     0 if($fuzzy || $inactive)
115 0         0 { info __xn"{domain}: one file with {ids} msgids, {f} fuzzy and {i} inactive translations",
116             "{domain}: {_count} files each {ids} msgids, {f} fuzzy and {i} inactive translations in total",
117             scalar(@$pots), domain => $domain, f => $fuzzy, ids => $msgids, i => $inactive;
118             }
119             else
120 0         0 { info __xn"{domain}: one file with {ids} msgids", "{domain}: {_count} files with each {ids} msgids",
121             scalar(@$pots), domain => $domain, ids => $msgids;
122             }
123             }
124             }
125              
126              
127             sub write(;$%)
128 3     3 1 1123 { my $self = shift;
129 3 100       17 my ($domain, %args) = @_ % 2 ? @_ : (undef, @_);
130              
131 3 100       29 unless(defined $domain) # write all
132 2         31 { $self->write($_) for $self->domains;
133 2         109 return;
134             }
135              
136 1 50       6 my $pots = delete $self->{LRE_domains}{$domain}
137             or return; # nothing found
138              
139 1         5 for my $pot (@$pots)
140 1         7 { $pot->updated;
141 1         8 $pot->write(%args);
142             }
143              
144 1         60 $self;
145             }
146              
147 1     1   1105 sub DESTROY() { $_[0]->write }
148              
149             sub _reset($$)
150 1     1   26 { my ($self, $domain, $fn) = @_;
151 1   33     14 my $pots = $self->{LRE_domains}{$domain} ||= $self->_read_pots($domain);
152 1         8 $_->removeReferencesTo($fn) for @$pots;
153             }
154              
155             sub _read_pots($)
156 1     1   4 { my ($self, $domain) = @_;
157              
158 1         8 my $index = $self->index;
159 1         5 my $charset = $self->charset;
160 1         9 my @pots = map Log::Report::Lexicon::POT->read($_, charset=> $charset), $index->list($domain);
161              
162 1         7 trace __xn"found one pot file for domain {domain}", "found {_count} pot files for domain {domain}", @pots, domain => $domain;
163              
164             return \@pots
165 1 50       114 if @pots;
166              
167             # new text-domain found, start template
168 1         6 my $fn = $index->addFile("$domain.$charset.po");
169 1         5 info __x"starting new textdomain {domain}, template in {filename}", domain => $domain, filename => $fn;
170              
171 1         114 my $pot = Log::Report::Lexicon::POT->new(
172             textdomain => $domain,
173             filename => $fn,
174             charset => $charset,
175             version => 0.01
176             );
177              
178 1         10 [ $pot ];
179             }
180              
181              
182             sub store($$$$;$)
183 12     12 1 30 { my ($self, $domain, $fn, $linenr, $msgid, $plural) = @_;
184              
185 12         39 my $textdomain = textdomain $domain;
186 12         250 my $context = $textdomain->contextRules;
187              
188 12         58 foreach my $pot ($self->pots($domain))
189 12         24 { my ($stripped, $msgctxts);
190 12 50       21 if($context)
191 0   0     0 { my $lang = $pot->language || 'en';
192 0         0 ($stripped, $msgctxts) = $context->expand($msgid, $lang);
193              
194 0 0 0     0 if($plural && $plural =~ m/\{[^}]*\<\w+/)
195 0         0 { error __x"no context tags allowed in plural `{msgid}'", msgid => $plural;
196             }
197             }
198             else
199 12         24 { $stripped = $msgid;
200             }
201              
202 12 50 33     38 $msgctxts && @$msgctxts
203             or $msgctxts = [undef];
204              
205             MSGCTXT:
206 12         25 foreach my $msgctxt (@$msgctxts)
207             {
208 12 50       37 if(my $po = $pot->msgid($stripped, $msgctxt))
209 0         0 { $po->addReferences( ["$fn:$linenr"]);
210 0 0       0 $po->plural($plural) if $plural;
211 0         0 next MSGCTXT;
212             }
213              
214 12 100       35 my $format = $stripped =~ m/\{/ ? 'perl-brace' : 'perl';
215 12         90 my $po = Log::Report::Lexicon::PO->new(
216             msgid => $stripped,
217             msgid_plural => $plural,
218             msgctxt => $msgctxt,
219             fuzzy => 1,
220             format => $format,
221             references => [ "$fn:$linenr" ]
222             );
223              
224 12         52 $pot->add($po);
225             }
226             }
227             }
228              
229             1;