File Coverage

blib/lib/WWW/TasteKid.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package WWW::TasteKid;
2              
3             #$Id$
4             # /* vim:et: set ts=4 sw=4 sts=4 tw=78: */
5              
6 7     7   258610 use 5.008001; # require perl 5.8.1 or later
  7         28  
  7         373  
7 7     7   42 use warnings;
  7         14  
  7         336  
8 7     7   46 use strict;
  7         18  
  7         268  
9              
10             #use criticism 'brutal';
11              
12 7     7   6333 use version; our $VERSION = qv('0.1.3');
  7         18756  
  7         45  
13              
14 7     7   13046 use Readonly;
  7         29623  
  7         469  
15 7     7   11815 use XML::LibXML (); # qw/:libxml/; # :all :libxml, :encoding :w3c
  0            
  0            
16             use Carp qw/croak/;
17             use Encode qw/encode/;
18             use LWP::Simple qw/get/;
19             use Data::Dumper qw/Dumper/;
20             use Scalar::Util qw/refaddr/;
21             use URI::Escape qw/uri_escape/;
22             use HTML::Entities qw/decode_entities/;
23             use Class::InsideOut qw/public private/;
24              
25             # should probably be using moose, just seems like
26             # overkill for a module this simple/small
27              
28             use WWW::TasteKidResult;
29              
30             Readonly my $API_URL => 'http://www.tastekid.com/ask/ws?q=';
31              
32             private query_store => my %query_store;
33             public set_xml_result => my %xml_result;
34             public get_xml_result => %xml_result;
35             public get_encoded_query => my %encoded_query;
36              
37             sub new {
38             my $class = shift;
39             my $self = bless \do { my $s }, $class;
40              
41             Class::InsideOut::register($self);
42              
43             $xml_result{ refaddr $self } = undef;
44             $encoded_query{ refaddr $self } = undef;
45             $query_store{ refaddr $self } = undef;
46              
47             return $self;
48             }
49              
50             sub query {
51             my ( $self, $arg_ref ) = @_;
52              
53             if ( !$arg_ref->{'name'} ) {
54             croak 'name argument is mandatory';
55             }
56              
57             if ( !exists $query_store{'query'} ) {
58             $query_store{'query'} = [];
59             }
60              
61             push @{ $query_store{'query'} }, $arg_ref;
62              
63             return;
64             }
65              
66             sub query_inspection {
67             print Dumper $query_store{'query'};
68             }
69              
70             sub ask {
71             my ( $self, $arg_ref ) = @_;
72              
73             my $query_str = q{};
74             foreach my $q ( @{ $query_store{'query'} } ) {
75             my $t = $q->{'type'} || q{};
76             my $n = $q->{'name'} || q{};
77              
78             if ($t) {
79             $query_str .= "$t:";
80             }
81              
82             if ($n) {
83             $query_str .= "$n,";
84             }
85             }
86              
87             # purge queries list
88             delete $query_store{ refaddr $self };
89              
90             $query_str =~ s/\,\z//xms;
91              
92             my $query = $API_URL . uri_escape($query_str);
93              
94             if ( $arg_ref->{'filter'} ) { $query .= "//$arg_ref->{'filter'}" }
95             if ( $arg_ref->{'verbose'} ) { $query .= '&verbose=1' }
96              
97             $encoded_query{ refaddr $self } = $query;
98              
99             my $r = get($query);
100              
101             if ( !$r ) { croak qq{unable to get $query} }
102              
103             $self->set_xml_result($r);
104              
105             return;
106              
107             }
108              
109             sub info_resource {
110             my ($self) = @_;
111             return $self->_common_resource('info');
112             }
113              
114             sub results_resource {
115             my ($self) = @_;
116             return $self->_common_resource('results');
117             }
118              
119             sub _common_resource {
120             my ( $self, $elem ) = @_;
121              
122             if ( caller ne 'WWW::TasteKid' ) { croak 'private method'; }
123              
124             my @return_req = ();
125              
126             my $parser = XML::LibXML->new();
127              
128             my $tstkd_xml = $parser->parse_string( $self->get_xml_result );
129              
130             my $xml_root = $tstkd_xml->documentElement;
131              
132             if ( !$xml_root
133             || $xml_root->nodeName ne 'similar' )
134             {
135             croak 'unknown file format recieved, cannot continue';
136             }
137              
138             return _parse_response( $xml_root, $elem );
139             }
140              
141             sub _parse_response {
142             my ( $xml_root, $elem ) = @_;
143              
144             if ( caller ne 'WWW::TasteKid' ) { croak 'private method'; }
145              
146             my $results_ref = [];
147              
148             #TODO 3 nested foreach?! geez, refactor me
149             foreach my $node ( $xml_root->childNodes ) {
150              
151             #warn $node->toString;
152              
153             #next unless $node->nodeName eq $elem;
154             if ( $node->nodeName ne $elem ) { next }
155              
156             foreach my $c_node ( $node->childNodes ) {
157             if ( $c_node->nodeName eq 'resource' ) {
158              
159             my $tkr = WWW::TasteKidResult->new;
160             foreach my $cc_node ( $c_node->childNodes ) {
161              
162             #next unless $tkr->can( lc $cc_node->nodeName );
163             if ( !$tkr->can( lc $cc_node->nodeName ) ) { next }
164              
165             my $text_content = $cc_node->textContent;
166             $text_content = encode( 'utf8', $text_content );
167              
168             $text_content = decode_entities($text_content);
169              
170             my $method_name = lc $cc_node->nodeName;
171             $tkr->$method_name($text_content);
172              
173             }
174             push @{$results_ref}, $tkr;
175             }
176             }
177             }
178             return $results_ref;
179             }
180              
181             1;
182              
183             __END__