File Coverage

blib/lib/WWW/Wikipedia/Entry.pm
Criterion Covered Total %
statement 104 107 97.2
branch 34 38 89.4
condition 3 6 50.0
subroutine 19 20 95.0
pod 12 12 100.0
total 172 183 93.9


line stmt bran cond sub pod time code
1             package WWW::Wikipedia::Entry;
2              
3 11     11   1375 use 5.006;
  11         36  
4 11     11   53 use strict;
  11         18  
  11         186  
5 11     11   46 use warnings;
  11         20  
  11         229  
6 11     11   5262 use Text::Autoformat;
  11         344479  
  11         685  
7 11     11   716 use WWW::Wikipedia;
  11         24  
  11         10373  
8              
9             our $VERSION = '2.05';
10              
11             =head1 NAME
12              
13             WWW::Wikipedia::Entry - A class for representing a Wikipedia Entry
14              
15             =head1 SYNOPSIS
16              
17             my $wiki = WWW::Wikipedia->new();
18             my $entry = $wiki->search( 'Perl' );
19             print $entry->text();
20              
21             my $entry_es = $entry->language( 'es' );
22             print $entry_es->text();
23              
24             =head1 DESCRIPTION
25              
26             WWW::Wikipedia::Entry objects are usually created using the search() method
27             on a WWW::Wikipedia object to search for a term. Once you've got an entry
28             object you can then extract pieces of information from the entry using
29             the following methods.
30              
31             =head1 METHODS
32              
33             =head2 new()
34              
35             You probably won't use this one, it's the constructor that is called
36             behind the scenes with the correct arguments by WWW::Wikipedia::search().
37              
38             =cut
39              
40             sub new {
41 14     14 1 68453 my ( $class, $raw, $src, %ops ) = @_;
42 14 50       1456 return if length( $raw ) == 0;
43 14   33     257 my $self = bless {
44             raw => $raw,
45             src => $src,
46             text => '',
47             fulltext => '',
48             cursor => 0,
49             related => [],
50             categories => [],
51             headings => [],
52             languages => {},
53             currentlang => ''
54             },
55             ref( $class ) || $class;
56 14         83 $self->_parse();
57              
58             # store un-"pretty"-ed version of text
59 14         361 $self->{ fulltext_basic } = $self->{ fulltext };
60 14         71 $self->{ text_basic } = $self->{ text };
61              
62 14 100       136 if ($ops{clean_html}) {
63 2         13 $self->{ fulltext } = _clean_html( $self->{ fulltext });
64 2         9 $self->{ text } = _clean_html( $self->{ text });
65             }
66              
67 14         77 $self->{ fulltext } = _pretty( $self->{ fulltext } );
68 14         3216704 $self->{ text } = _pretty( $self->{ text } );
69 14         169835 return ( $self );
70             }
71              
72             =head2 text()
73              
74             The brief text for the entry. This will provide the first paragraph of
75             text; basically everything up to the first heading. Ordinarily this will
76             be what you want to use. When there doesn't appear to be summary text you
77             will be returned the fulltext instead.
78              
79             If text() returns nothing then you probably are looking at a disambiguation
80             entry, and should use related() to lookup more specific entries.
81              
82             =cut
83              
84             sub text {
85 9     9 1 4598 my $self = shift;
86 9 100       98 return $self->{ text } if $self->{ text };
87 2         13 return $self->fulltext();
88             }
89              
90             =head2 text_basic()
91              
92             The same as C, but not run through Text::Autoformat.
93              
94             =cut
95              
96             sub text_basic {
97 1     1 1 573 my $self = shift;
98 1 50       9 return $self->{ text_basic } if $self->{ text_basic };
99 0         0 return $self->fulltext_basic();
100             }
101              
102             =head2 fulltext()
103              
104             Returns the full text for the entry, which can be extensive.
105              
106             =cut
107              
108             sub fulltext {
109 4     4 1 870 my $self = shift;
110 4         259 return $self->{ fulltext };
111             }
112              
113             =head2 fulltext_basic()
114              
115             The same as C, but not run through Text::Autoformat.
116              
117             =cut
118              
119             sub fulltext_basic {
120 0     0 1 0 my $self = shift;
121 0         0 return $self->{ fulltext_basic };
122             }
123              
124              
125             =head2 title()
126              
127             Returns a title of the entry.
128              
129             =cut
130              
131             sub title {
132 2     2 1 6 my $self = shift;
133 2         9 return $self->{ title };
134             }
135              
136             =head2 related()
137              
138             Returns a list of terms in the wikipedia that are mentioned in the
139             entry text.
140              
141             =cut
142              
143             sub related {
144 2     2 1 982 return ( @{ shift->{ related } } );
  2         12  
145             }
146              
147             =head2 categories()
148              
149             Returns a list of categories which the entry is part of. So Perl is part
150             of the Programming languages category.
151              
152             =cut
153              
154             sub categories {
155 2     2 1 5 return ( @{ shift->{ categories } } );
  2         10  
156             }
157              
158             =head2 headings()
159              
160             Returns a list of headings used in the entry.
161              
162             =cut
163              
164             sub headings {
165 2     2 1 6 return ( @{ shift->{ headings } } );
  2         13  
166             }
167              
168             =head2 raw()
169              
170             Returns the raw wikitext for the entry.
171              
172             =cut
173              
174             sub raw {
175 11     11 1 31 my $self = shift;
176 11         145 return $self->{ raw };
177             }
178              
179             =head2 language()
180              
181             With no parameters, it will return the current language of the entry. By
182             specifying a two-letter language code, it will return the same entry in that
183             language, if available.
184              
185             NOTE: Generally, Wikipedia no longer uses language tags stored on a page.
186             Rather, languages are driven from wikidata, which this module does not
187             query. You will find for most pages there are no other languages available,
188             based on how this method currently works..
189              
190             =cut
191              
192             sub language {
193 3     3 1 8 my $self = shift;
194 3         7 my $lang = shift;
195              
196 3 100       18 return $self->{ currentlang } unless defined $lang;
197 1 50       5 return undef unless exists $self->{ languages }->{ $lang };
198              
199 1         7 my $wiki = WWW::Wikipedia->new( language => $lang );
200 1         5 return $wiki->search( $self->{ languages }->{ $lang } );
201             }
202              
203             =head2 languages()
204              
205             Returns an array of two letter language codes denoting the languages in which
206             this entry is available.
207              
208             =cut
209              
210             sub languages {
211 2     2 1 1090 my $self = shift;
212              
213 2         4 return keys %{ $self->{ languages } };
  2         17  
214             }
215              
216             ## messy internal routine for barebones parsing of wikitext
217              
218             sub _parse {
219 14     14   34 my $self = shift;
220 14         65 my $raw = $self->{ raw };
221 14         35 my $src = $self->{ src };
222              
223             # Add current language
224 14         102 my ( $lang ) = ( $src =~ /http:\/\/(..)/ );
225 14         79 my $title = ( split( /\//, $src ) )[ -1 ];
226              
227 14 100       79 if( $title =~ m{\?title=} ) {
228 11         61 ( $title ) = $src =~ m{\?title=([^\&]+)};
229 11         39 $title =~ s{_}{ }g;
230             }
231              
232 14         57 $self->{ currentlang } = $lang;
233 14         48 $self->{ languages }->{ $lang } = $title;
234 14         76 $self->{ title } = $title;
235              
236 14         1503 for (
237             $self->{ cursor } = 0;
238             $self->{ cursor } < length( $raw );
239             $self->{ cursor }++
240             )
241             {
242              
243 246310         425783 pos( $raw ) = $self->{ cursor };
244              
245             ## [[ ... ]]
246 246310 100       1571648 if ( $raw =~ /\G\[\[ *(.*?) *\]\]/ ) {
    100          
    100          
    100          
    100          
247 1932         4565 my $directive = $1;
248 1932         4160 $self->{ cursor } += length( $& ) - 1;
249 1932 100       5162 if ( $directive =~ /\:/ ) {
    100          
250 174         604 my ( $type, $text ) = split /:/, $directive;
251 174 100       620 if ( lc( $type ) eq 'category' ) {
252 45         71 push( @{ $self->{ categories } }, $text );
  45         116  
253             }
254              
255             # language codes
256 174 100 66     791 if ( length( $type ) == 2 and lc( $type ) eq $type ) {
257 41         134 $self->{ languages }->{ $type } = $text;
258             }
259             }
260             elsif ( $directive =~ /\|/ ) {
261 544         2019 my ( $lookup, $name ) = split /\|/, $directive;
262 544         1182 $self->{ fulltext } .= $name;
263 544 100       1375 push( @{ $self->{ related } }, $lookup ) if $lookup !~ /^#/;
  539         2010  
264             }
265             else {
266 1214         2096 $self->{ fulltext } .= $directive;
267 1214         1592 push( @{ $self->{ related } }, $directive );
  1214         4155  
268             }
269             }
270              
271             ## === heading 2 ===
272             elsif ( $raw =~ /\G=== *(.*?) *===/ ) {
273             ### don't bother storing these headings
274 92         297 $self->{ fulltext } .= $1;
275 92         246 $self->{ cursor } += length( $& ) - 1;
276 92         244 next;
277             }
278              
279             ## == heading 1 ==
280             elsif ( $raw =~ /\G== *(.*?) *==/ ) {
281 112         197 push( @{ $self->{ headings } }, $1 );
  112         414  
282 112 100       394 $self->{ text } = $self->{ fulltext } if !$self->{ seenHeading };
283 112         228 $self->{ seenHeading } = 1;
284 112         295 $self->{ fulltext } .= $1;
285 112         278 $self->{ cursor } += length( $& ) - 1;
286 112         303 next;
287             }
288              
289             ## '' italics ''
290             elsif ( $raw =~ /\G'' *(.*?) *''/ ) {
291 908         2088 $self->{ fulltext } .= $1;
292 908         1643 $self->{ cursor } += length( $& ) - 1;
293 908         2219 next;
294             }
295              
296             ## {{ disambig }}
297             elsif ( $raw =~ /\G\{\{ *(.*?) *\}\}/ ) {
298             ## ignore for now
299 370         1111 $self->{ cursor } += length( $& ) - 1;
300 370         953 next;
301             }
302              
303             else {
304 242896         659531 $self->{ fulltext } .= substr( $raw, $self->{ cursor }, 1 );
305             }
306             }
307             }
308              
309             # future versions might clean tag contents for some specific ones.
310             sub _clean_html {
311 4     4   49 my $text = shift;
312             # force first letter so that standalone < might be kept
313 4         383 $text =~ s{<[/a-zA-Z!][^>]+>}{}g;
314 4         33 return $text;
315             }
316              
317             sub _pretty {
318 28     28   280 my $text = shift;
319              
320             # Text::Autoformat v1.13 chokes on strings that are one or more "\n"
321 28 50       185 return '' if $text =~ m/^\n+$/;
322 28         300 return autoformat(
323             $text,
324             { left => 0,
325             right => 80,
326             justify => 'left',
327             all => 1
328             }
329             );
330             }
331              
332             =head1 AUTHORS
333              
334             Ed Summers Eehs@pobox.comE
335              
336             Brian Cassidy Ebricas@cpan.orgE
337              
338             =head1 COPYRIGHT AND LICENSE
339              
340             Copyright 2003-2017 by Ed Summers
341              
342             This library is free software; you can redistribute it and/or modify
343             it under the same terms as Perl itself.
344              
345             =cut
346              
347             1;