File Coverage

blib/lib/Net/Social/Mapper/Persona.pm
Criterion Covered Total %
statement 34 86 39.5
branch 6 20 30.0
condition 2 24 8.3
subroutine 15 27 55.5
pod 18 18 100.0
total 75 175 42.8


line stmt bran cond sub pod time code
1             package Net::Social::Mapper::Persona;
2              
3 11     11   1065 use strict;
  11         21  
  11         416  
4 11     11   5309 use JSON::Any;
  11         152726  
  11         85  
5              
6             =head1 NAME
7              
8             Net::Social::Mapper::Persona - an object representing an internet persona
9              
10             =head1 SYNOPSIS
11              
12             See C
13              
14             =head1 METHODS
15              
16             =cut
17              
18             =head2 new [opt[s]]
19              
20             Create a new persona.
21              
22             =cut
23             sub new {
24 29     29 1 2763 my $class = shift;
25 29   50     115 my $user = shift || return undef;
26 29   50     106 my $service = shift || return undef;
27 29         108 my %opts = @_;
28              
29 29         178 $opts{user} = $user;
30 29         84 $opts{service} = $service;
31 29         115 my $self = bless \%opts, $class;
32              
33 29 100       162 $self->_init || return;
34 25         470 return $self;
35             }
36              
37 0     0   0 sub _init { 1 }
38              
39             =head2 user
40              
41             The user name of this persona
42              
43             =cut
44 19     19 1 129 sub user { shift->_do('user', @_) }
45              
46             =head2 service
47              
48             The service for this persona
49              
50             =cut
51 24     24 1 141 sub service { shift->_do('service', @_) }
52              
53             =head2 domain
54              
55             The domain for this service
56              
57             =cut
58 11     11 1 40 sub domain { shift->_do('domain', @_) }
59              
60              
61             =head2 favicon
62              
63             The url to the favicon for this service
64              
65             =cut
66             sub favicon {
67 0     0 1 0 my $self = shift;
68 0   0     0 return $self->_do('favicon') || "http://".$self->domain."/favicon.ico";
69             }
70              
71             =head2 name
72              
73             The canonical name of the service.
74              
75             =cut
76 0     0 1 0 sub name { shift->_do('name', @_) }
77              
78             =head2 feeds
79              
80             Returns a hash of feeds (which might be empty)
81              
82             =cut
83 5     5 1 37 sub feeds { shift->_do_array('feeds', @_) }
84              
85             sub _do {
86 64     64   139 my $self = shift;
87 64         104 my $what = shift;
88 64 50       184 $self->{$what} = shift if @_;
89 64         411 return $self->{$what};
90             }
91              
92             sub _do_array {
93 5     5   11 my $self = shift;
94 5         9 my $what = shift;
95 5 50       20 $self->{$what} = [@_] if @_;
96 5 100       8 return @{$self->{$what}||[]};
  5         45  
97             }
98              
99             sub _do_array_with_defaults {
100 0     0   0 my $self = shift;
101 0         0 my $what = shift;
102 0         0 my $default = shift;
103 0         0 my @return = $self->_do_array($what, @_);
104 0 0       0 @return = ($default) unless @return;
105 0         0 return @return;
106             }
107              
108             =head2 types
109              
110             Return what type(s) feed objects are.
111              
112             Will almost certainly be one of - posts (default), notes, photos, videos
113              
114             =cut
115 0     0 1 0 sub types { shift->_do_array_with_defaults('types', 'posts', @_) }
116              
117             =head2 verbs
118              
119             Return what verb(s) feed objects are.
120              
121             Will almost certainly be one of - post (default), favorite
122              
123             =cut
124 0     0 1 0 sub verbs { shift->_do_array_with_defaults('verbs', 'post', @_) }
125              
126             =head2 persona_name
127              
128             A canonical short name for this persona. Generally C@C
129              
130             =cut
131             sub persona_name {
132 0     0 1 0 my $self = shift;
133 0         0 return $self->user.'@'.$self->service;
134             }
135              
136             =head2 elsewhere
137              
138             Get other personas for this user
139              
140             =cut
141             sub elsewhere {
142 0     0 1 0 my $self = shift;
143 0         0 my $url = URI->new("http://socialgraph.apis.google.com/otherme");
144 0         0 $url->query_form( q => $self->_elsewhere_param );
145 0   0     0 my $page = $self->mapper->get("$url") || return ();
146 0   0     0 my $info = eval { $self->_json->decode($page) } || return ();
147 0         0 my @personas;
148 0         0 foreach my $url (keys %$info) {
149 0         0 my $attributes = $info->{$url}->{attributes};
150 0 0       0 next unless keys %$attributes;
151 0   0     0 my $persona = $self->_attributes_to_persona($url, $attributes) || next;
152 0         0 push @personas, $persona;
153             }
154 0         0 return @personas;
155             }
156              
157             =head2 mapper
158              
159             Return the C object for this persona.
160              
161             =cut
162 21     21 1 164 sub mapper { shift->{_mapper} }
163              
164             =head1 METHODS WHICH MIGHT RETURN UNDEF
165              
166             =cut
167              
168             =head2 homepage
169              
170             The url of their homepage on this service
171              
172             =cut
173 4     4 1 16 sub homepage { shift->_do('homepage', @_) }
174              
175             =head2 profile
176              
177             The url of their profile on this service.
178              
179             =cut
180 1     1 1 3 sub profile { shift->_do('profile', @_) }
181              
182             =head2 foaf
183              
184             The url of their foaf feed on this service.
185              
186             =cut
187 1     1 1 5 sub foaf { shift->_do('foaf', @_) }
188              
189             =head2 full_name
190              
191             Returns the full name of the persona if available
192              
193             =cut
194 1     1 1 5 sub full_name { shift->_do('full_name', @_) }
195              
196             =head2 id
197              
198             Returns the id of the persona on the service if applicable
199              
200             =cut
201 3     3 1 13 sub id { shift->_do('id', @_) }
202              
203             =head2 photo
204              
205             Returns the profile picture of the person on the service if available
206              
207             =cut
208 0     0 1   sub photo { shift->_do('photo', @_) }
209              
210             my %_attribute_map = (
211             fn => "fullname",
212             url => "homepage",
213             profile => "profile",
214             photo => "photo",
215             foaf => "foaf",
216             feed => "feed",
217             );
218              
219              
220             sub _attributes_to_persona {
221 0     0     my $self = shift;
222 0           my $url = shift;
223 0           my $attributes = shift;
224 0           my $mapper = $self->mapper;
225            
226             # work out what persona this is
227 0           my ($user, $service) = $mapper->sitemap->url_to_service($url);
228             # and instantiate it
229 0           my $persona = $mapper->persona($user, $service);
230              
231             # collapse the atom and rss feeds down
232 0           foreach my $feed (qw(atom rss)) {
233 0 0         push @{$attributes->{feeds}}, delete $attributes->{$feed} if exists $attributes->{$feed};
  0            
234             }
235              
236             # Now go through and add an additional data in
237 0           foreach my $key (keys %$attributes) {
238             # Skip what we're not interested in
239 0   0       my $name = $_attribute_map{$key} || next;
240              
241             # If either is an array already then combine the values
242 0 0 0       if (ref $persona->{$name} eq 'ARRAY' || ref $attributes->{$key} eq 'ARRAY') {
243 0 0         my @to = ref($persona->{$name}) ? @{$persona->{$name}} : ($persona->{$name});
  0            
244 0 0         my @from = ref($attributes->{$key}) ? @{$attributes->{$key}} : ($attributes->{$key});
  0            
245 0           my %tmp = map { $_ => 1 } (@to, @from);
  0            
246 0           $attributes->{$key} = [ keys %tmp ];
247             }
248            
249             # Now merge the values. This assumes Google knows more than we do. Which may be wrong.
250 0           $persona->{$name} = $attributes->{$key};
251             }
252 0           return $persona;
253             }
254              
255             sub _json {
256 0     0     my $self = shift;
257 0   0       return $self->{_json} ||= JSON::Any->new;
258             }
259              
260             sub _elsewhere_param {
261 0     0     my $self = shift;
262 0   0       return $self->homepage || $self->user;
263             }
264              
265             1;
266