File Coverage

blib/lib/WWW/Wikipedia/Entry.pm
Criterion Covered Total %
statement 99 107 92.5
branch 33 38 86.8
condition 3 6 50.0
subroutine 18 20 90.0
pod 12 12 100.0
total 165 183 90.1


line stmt bran cond sub pod time code
1             package WWW::Wikipedia::Entry;
2              
3 10     10   1632 use 5.006;
  10         33  
4 10     10   51 use strict;
  10         16  
  10         203  
5 10     10   45 use warnings;
  10         17  
  10         245  
6 10     10   9654 use Text::Autoformat;
  10         516380  
  10         1091  
7 10     10   1246 use WWW::Wikipedia;
  10         23  
  10         13600  
8              
9             our $VERSION = '2.04';
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 98030 my ( $class, $raw, $src, %ops ) = @_;
42 14 50       1337 return if length( $raw ) == 0;
43 14   33     288 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         72 $self->_parse();
57              
58             # store un-"pretty"-ed version of text
59 14         242 $self->{ fulltext_basic } = $self->{ fulltext };
60 14         58 $self->{ text_basic } = $self->{ text };
61              
62 14 50       69 if ($ops{clean_html}) {
63 0         0 $self->{ fulltext } = _clean_html( $self->{ fulltext });
64 0         0 $self->{ text } = _clean_html( $self->{ text });
65             }
66              
67 14         66 $self->{ fulltext } = _pretty( $self->{ fulltext } );
68 14         2760823 $self->{ text } = _pretty( $self->{ text } );
69 14         142628 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 7     7 1 4858 my $self = shift;
86 7 100       76 return $self->{ text } if $self->{ text };
87 2         9 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 646 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 773 my $self = shift;
110 4         264 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 5 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 955 return ( @{ shift->{ related } } );
  2         10  
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 3 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 5 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 23 my $self = shift;
176 11         193 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             =cut
186              
187             sub language {
188 4     4 1 487 my $self = shift;
189 4         7 my $lang = shift;
190              
191 4 100       23 return $self->{ currentlang } unless defined $lang;
192 2 50       9 return undef unless exists $self->{ languages }->{ $lang };
193              
194 2         18 my $wiki = WWW::Wikipedia->new( language => $lang );
195 2         11 return $wiki->search( $self->{ languages }->{ $lang } );
196             }
197              
198             =head2 languages()
199              
200             Returns an array of two letter language codes denoting the languages in which
201             this entry is available.
202              
203             =cut
204              
205             sub languages {
206 2     2 1 1219 my $self = shift;
207              
208 2         3 return keys %{ $self->{ languages } };
  2         15  
209             }
210              
211             ## messy internal routine for barebones parsing of wikitext
212              
213             sub _parse {
214 14     14   32 my $self = shift;
215 14         56 my $raw = $self->{ raw };
216 14         34 my $src = $self->{ src };
217              
218             # Add current language
219 14         90 my ( $lang ) = ( $src =~ /http:\/\/(..)/ );
220 14         80 my $title = ( split( /\//, $src ) )[ -1 ];
221              
222 14 100       86 if( $title =~ m{\?title=} ) {
223 11         63 ( $title ) = $src =~ m{\?title=([^\&]+)};
224 11         33 $title =~ s{_}{ }g;
225             }
226              
227 14         43 $self->{ currentlang } = $lang;
228 14         48 $self->{ languages }->{ $lang } = $title;
229 14         93 $self->{ title } = $title;
230              
231 14         1350 for (
232             $self->{ cursor } = 0;
233             $self->{ cursor } < length( $raw );
234             $self->{ cursor }++
235             )
236             {
237              
238 216464         397476 pos( $raw ) = $self->{ cursor };
239              
240             ## [[ ... ]]
241 216464 100       6459134 if ( $raw =~ /\G\[\[ *(.*?) *\]\]/ ) {
    100          
    100          
    100          
    100          
242 1680         3835 my $directive = $1;
243 1680         3668 $self->{ cursor } += length( $& ) - 1;
244 1680 100       5059 if ( $directive =~ /\:/ ) {
    100          
245 156         557 my ( $type, $text ) = split /:/, $directive;
246 156 100       642 if ( lc( $type ) eq 'category' ) {
247 39         57 push( @{ $self->{ categories } }, $text );
  39         103  
248             }
249              
250             # language codes
251 156 100 66     25710 if ( length( $type ) == 2 and lc( $type ) eq $type ) {
252 45         224 $self->{ languages }->{ $type } = $text;
253             }
254             }
255             elsif ( $directive =~ /\|/ ) {
256 483         1898 my ( $lookup, $name ) = split /\|/, $directive;
257 483         899 $self->{ fulltext } .= $name;
258 483 100       1225 push( @{ $self->{ related } }, $lookup ) if $lookup !~ /^#/;
  480         2256  
259             }
260             else {
261 1041         1691 $self->{ fulltext } .= $directive;
262 1041         1155 push( @{ $self->{ related } }, $directive );
  1041         4528  
263             }
264             }
265              
266             ## === heading 2 ===
267             elsif ( $raw =~ /\G=== *(.*?) *===/ ) {
268             ### don't bother storing these headings
269 76         194 $self->{ fulltext } .= $1;
270 76         188 $self->{ cursor } += length( $& ) - 1;
271 76         228 next;
272             }
273              
274             ## == heading 1 ==
275             elsif ( $raw =~ /\G== *(.*?) *==/ ) {
276 88         117 push( @{ $self->{ headings } }, $1 );
  88         367  
277 88 100       289 $self->{ text } = $self->{ fulltext } if !$self->{ seenHeading };
278 88         179 $self->{ seenHeading } = 1;
279 88         213 $self->{ fulltext } .= $1;
280 88         214 $self->{ cursor } += length( $& ) - 1;
281 88         282 next;
282             }
283              
284             ## '' italics ''
285             elsif ( $raw =~ /\G'' *(.*?) *''/ ) {
286 484         1146 $self->{ fulltext } .= $1;
287 484         963 $self->{ cursor } += length( $& ) - 1;
288 484         1393 next;
289             }
290              
291             ## {{ disambig }}
292             elsif ( $raw =~ /\G\{\{ *(.*?) *\}\}/ ) {
293             ## ignore for now
294 277         946 $self->{ cursor } += length( $& ) - 1;
295 277         873 next;
296             }
297              
298             else {
299 213859         717716 $self->{ fulltext } .= substr( $raw, $self->{ cursor }, 1 );
300             }
301             }
302             }
303              
304             # future versions might clean tag contents for some specific ones.
305             sub _clean_html {
306 0     0   0 my $text = shift;
307             # force first letter so that standalone < might be kept
308 0         0 $text =~ s{<[/a-zA-Z!][^>]+>}{}g;
309 0         0 return $text;
310             }
311              
312             sub _pretty {
313 28     28   212 my $text = shift;
314              
315             # Text::Autoformat v1.13 chokes on strings that are one or more "\n"
316 28 50       143 return '' if $text =~ m/^\n+$/;
317 28         260 return autoformat(
318             $text,
319             { left => 0,
320             right => 80,
321             justify => 'left',
322             all => 1
323             }
324             );
325             }
326              
327             =head1 AUTHORS
328              
329             Ed Summers Eehs@pobox.comE
330              
331             Brian Cassidy Ebricas@cpan.orgE
332              
333             =head1 COPYRIGHT AND LICENSE
334              
335             Copyright 2003-2015 by Ed Summers
336              
337             This library is free software; you can redistribute it and/or modify
338             it under the same terms as Perl itself.
339              
340             =cut
341              
342             1;