File Coverage

blib/lib/WWW/Wikipedia/Entry.pm
Criterion Covered Total %
statement 97 107 90.6
branch 32 38 84.2
condition 3 6 50.0
subroutine 18 20 90.0
pod 12 12 100.0
total 162 183 88.5


line stmt bran cond sub pod time code
1             package WWW::Wikipedia::Entry;
2              
3 10     10   1724 use 5.006;
  10         34  
4 10     10   49 use strict;
  10         20  
  10         210  
5 10     10   49 use warnings;
  10         16  
  10         283  
6 10     10   9792 use Text::Autoformat;
  10         1308155  
  10         1280  
7 10     10   1441 use WWW::Wikipedia;
  10         22  
  10         14351  
8              
9             our $VERSION = '2.03';
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 3     3 1 1986 my ( $class, $raw, $src, %ops ) = @_;
42 3 50       18 return if length( $raw ) == 0;
43 3   33     50 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 3         11 $self->_parse();
57              
58             # store un-"pretty"-ed version of text
59 3         77 $self->{ fulltext_basic } = $self->{ fulltext };
60 3         17 $self->{ text_basic } = $self->{ text };
61              
62 3 50       15 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 3         16 $self->{ fulltext } = _pretty( $self->{ fulltext } );
68 3         586795 $self->{ text } = _pretty( $self->{ text } );
69 3         9072 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 2     2 1 1638 my $self = shift;
86 2 100       11 return $self->{ text } if $self->{ text };
87 1         5 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 603 my $self = shift;
98 1 50       12 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 1     1 1 3 my $self = shift;
110 1         8 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         11 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 1001 return ( @{ shift->{ related } } );
  2         11  
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         12  
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 4 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 2     2 1 7 my $self = shift;
176 2         10 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 2     2 1 6 my $self = shift;
189 2         3 my $lang = shift;
190              
191 2 100       12 return $self->{ currentlang } unless defined $lang;
192 1 50       6 return undef unless exists $self->{ languages }->{ $lang };
193              
194 1         9 my $wiki = WWW::Wikipedia->new( language => $lang );
195 1         6 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 1     1 1 485 my $self = shift;
207              
208 1         3 return keys %{ $self->{ languages } };
  1         8  
209             }
210              
211             ## messy internal routine for barebones parsing of wikitext
212              
213             sub _parse {
214 3     3   6 my $self = shift;
215 3         13 my $raw = $self->{ raw };
216 3         6 my $src = $self->{ src };
217              
218             # Add current language
219 3         17 my ( $lang ) = ( $src =~ /http:\/\/(..)/ );
220 3         13 my $title = ( split( /\//, $src ) )[ -1 ];
221              
222 3 50       18 if( $title =~ m{\?title=} ) {
223 0         0 ( $title ) = $src =~ m{\?title=([^\&]+)};
224 0         0 $title =~ s{_}{ }g;
225             }
226              
227 3         7 $self->{ currentlang } = $lang;
228 3         9 $self->{ languages }->{ $lang } = $title;
229 3         62 $self->{ title } = $title;
230              
231 3         16 for (
232             $self->{ cursor } = 0;
233             $self->{ cursor } < length( $raw );
234             $self->{ cursor }++
235             )
236             {
237              
238 35932         68183 pos( $raw ) = $self->{ cursor };
239              
240             ## [[ ... ]]
241 35932 100       1526645 if ( $raw =~ /\G\[\[ *(.*?) *\]\]/ ) {
    100          
    100          
    100          
    100          
242 266         611 my $directive = $1;
243 266         540 $self->{ cursor } += length( $& ) - 1;
244 266 100       755 if ( $directive =~ /\:/ ) {
    100          
245 46         123 my ( $type, $text ) = split /:/, $directive;
246 46 100       115 if ( lc( $type ) eq 'category' ) {
247 3         5 push( @{ $self->{ categories } }, $text );
  3         9  
248             }
249              
250             # language codes
251 46 100 66     224 if ( length( $type ) == 2 and lc( $type ) eq $type ) {
252 41         204 $self->{ languages }->{ $type } = $text;
253             }
254             }
255             elsif ( $directive =~ /\|/ ) {
256 63         202 my ( $lookup, $name ) = split /\|/, $directive;
257 63         114 $self->{ fulltext } .= $name;
258 63 100       163 push( @{ $self->{ related } }, $lookup ) if $lookup !~ /^#/;
  61         280  
259             }
260             else {
261 157         227 $self->{ fulltext } .= $directive;
262 157         171 push( @{ $self->{ related } }, $directive );
  157         720  
263             }
264             }
265              
266             ## === heading 2 ===
267             elsif ( $raw =~ /\G=== *(.*?) *===/ ) {
268             ### don't bother storing these headings
269 4         17 $self->{ fulltext } .= $1;
270 4         14 $self->{ cursor } += length( $& ) - 1;
271 4         14 next;
272             }
273              
274             ## == heading 1 ==
275             elsif ( $raw =~ /\G== *(.*?) *==/ ) {
276 26         36 push( @{ $self->{ headings } }, $1 );
  26         104  
277 26 100       73 $self->{ text } = $self->{ fulltext } if !$self->{ seenHeading };
278 26         38 $self->{ seenHeading } = 1;
279 26         62 $self->{ fulltext } .= $1;
280 26         52 $self->{ cursor } += length( $& ) - 1;
281 26         126 next;
282             }
283              
284             ## '' italics ''
285             elsif ( $raw =~ /\G'' *(.*?) *''/ ) {
286 96         205 $self->{ fulltext } .= $1;
287 96         170 $self->{ cursor } += length( $& ) - 1;
288 96         263 next;
289             }
290              
291             ## {{ disambig }}
292             elsif ( $raw =~ /\G\{\{ *(.*?) *\}\}/ ) {
293             ## ignore for now
294 4         14 $self->{ cursor } += length( $& ) - 1;
295 4         14 next;
296             }
297              
298             else {
299 35536         115078 $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 6     6   55 my $text = shift;
314              
315             # Text::Autoformat v1.13 chokes on strings that are one or more "\n"
316 6 50       40 return '' if $text =~ m/^\n+$/;
317 6         69 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;