File Coverage

blib/lib/Web/Microformats2/Item.pm
Criterion Covered Total %
statement 51 53 96.2
branch 8 10 80.0
condition 6 9 66.6
subroutine 10 10 100.0
pod 4 7 57.1
total 79 89 88.7


line stmt bran cond sub pod time code
1             package Web::Microformats2::Item;
2 2     2   14 use Moose;
  2         4  
  2         20  
3 2     2   24802 use Carp;
  2         5  
  2         1800  
4              
5             has 'properties' => (
6             is => 'ro',
7             isa => 'HashRef',
8             traits => ['Hash'],
9             default => sub { {} },
10             handles => {
11             has_properties => 'count',
12             has_property => 'get',
13             },
14             );
15              
16             has 'p_properties' => (
17             is => 'ro',
18             isa => 'HashRef',
19             traits => ['Hash'],
20             default => sub { {} },
21             handles => {
22             has_p_properties => 'count',
23             has_p_property => 'get',
24             },
25             );
26              
27             has 'u_properties' => (
28             is => 'ro',
29             isa => 'HashRef',
30             traits => ['Hash'],
31             default => sub { {} },
32             handles => {
33             has_u_properties => 'count',
34             has_u_property => 'get',
35             },
36             );
37              
38             has 'e_properties' => (
39             is => 'ro',
40             isa => 'HashRef',
41             traits => ['Hash'],
42             default => sub { {} },
43             handles => {
44             has_e_properties => 'count',
45             has_e_property => 'get',
46             },
47             );
48              
49             has 'dt_properties' => (
50             is => 'ro',
51             isa => 'HashRef',
52             traits => ['Hash'],
53             default => sub { {} },
54             handles => {
55             has_dt_properties => 'count',
56             has_dt_property => 'get',
57             },
58             );
59             has 'parent' => (
60             is => 'ro',
61             isa => 'Maybe[Web::Microformats2::Item]',
62             weak_ref => 1,
63             );
64              
65             has 'children' => (
66             is => 'ro',
67             isa => 'ArrayRef[Web::Microformats2::Item]',
68             default => sub { [] },
69             traits => ['Array'],
70             handles => {
71             add_child => 'push',
72             has_children => 'count',
73             },
74             );
75              
76             has 'types' => (
77             is => 'ro',
78             isa => 'ArrayRef[Str]',
79             required => 1,
80             traits => ['Array'],
81             handles => {
82             find_type => 'first',
83             },
84              
85             );
86              
87             has 'value' => (
88             is => 'rw',
89             isa => 'Maybe[Str]',
90             );
91              
92             has 'last_seen_date' => (
93             is => 'rw',
94             isa => 'Maybe[DateTime]',
95             );
96              
97             sub add_property {
98 418     418 0 562 my $self = shift;
99              
100 418         740 my ( $key, $value ) = @_;
101              
102 418         1939 my ( $prefix, $base ) = $key =~ /^(\w+)-(.*)$/;
103              
104 418 50 33     1443 unless ( $prefix && $base ) {
105 0         0 croak "You must call add_property with the full property name, "
106             . "including its prefix. (e.g. 'p-name', not 'name' )";
107             }
108              
109 418         557 my $base_method = "properties";
110 418         785 my $prefix_method = "${prefix}_properties";
111              
112 418         764 foreach ($base_method, $prefix_method ) {
113 836   100     21617 $self->$_->{$base} ||= [];
114 836         1033 push @{ $self->$_->{$base} }, $value;
  836         18762  
115             }
116             }
117              
118             # add_base_property: Like add_property, but don't look for or insist on
119             # prefixes. Good for inflating from JSON, which has no
120             # prefix information.
121             sub add_base_property {
122 8     8 0 12 my $self = shift;
123              
124 8         16 my ( $key, $value ) = @_;
125              
126 8   50     193 $self->properties->{$key} ||= [];
127 8         13 push @{ $self->properties->{$key} }, $value;
  8         177  
128             }
129              
130             sub get_properties {
131 40     40 1 68 my $self = shift;
132              
133 40         84 my ( $key ) = @_;
134              
135 40   100     186 return $self->{properties}->{$key} || [];
136             }
137              
138             sub get_property {
139 3     3 1 7 my $self = shift;
140              
141 3         9 my $properties_ref = $self->get_properties( @_ );
142              
143 3 50       9 if ( @$properties_ref > 1 ) {
144 0         0 carp "get_property called with multiple properties set\n";
145             }
146              
147 3         13 return $properties_ref->[0];
148              
149             }
150              
151             sub has_type {
152 4     4 1 17 my $self = shift;
153 4         10 my ( $type ) = @_;
154              
155 4         18 $type =~ s/^h-//;
156              
157 4     4   261 return $self->find_type( sub { $_ eq $type } );
  4         33  
158             }
159              
160             sub all_types {
161 2     2 1 958 my $self = shift;
162 2         6 my ( %args ) = @_;
163              
164 2         3 my @types = @{ $self->types };
  2         64  
165              
166             # We add the 'h-' prefix to returned types unless told not to.
167 2 100       8 unless ( $args{ 'no_prefixes' } ) {
168 1         4 @types = map { "h-$_" } @types;
  1         5  
169             }
170              
171 2         7 return @types;
172             }
173              
174             sub TO_JSON {
175 143     143 0 250 my $self = shift;
176              
177             my $data = {
178             properties => $self->properties,
179 143         3343 type => [ map { "h-$_" } @{ $self->types } ],
  145         559  
  143         3022  
180             };
181 143 100       3192 if ( defined $self->value ) {
182 39         845 $data->{value} = $self->value;
183             }
184 143 100       194 if ( @{$self->children} ) {
  143         3112  
185 9         195 $data->{children} = $self->children;
186             }
187 143         1979 return $data;
188             }
189              
190             1;
191              
192              
193             =pod
194              
195             =head1 NAME
196              
197             Web::Microformats2::Item - A parsed Microformats2 item
198              
199             =head1 DESCRIPTION
200              
201             An object of this class represents a Microformats2 item, contained
202             within a larger, parsed Microformats2 data structure. An item represents
203             a single semantically meaningful something-or-other: an article, a
204             person, a photograph, et cetera.
205              
206             The expected use-case is that you will never directly construct item
207             objects. Instead, your code will receive item objects by querying a
208             L<Web::Microformats2::Document> instance, itself created by running
209             Microformats2-laden HTML or JSON through a L<Web::Microformats2::Parser>
210             object.
211              
212             See L<Web::Microformats2> for further context and purpose.
213              
214             =head1 METHODS
215              
216             =head2 Object Methods
217              
218             =head3 get_properties
219              
220             $properties_ref = $item->get_properties( $property_key )
221              
222             # To get all "u-url" properties of this item:
223             $urls = $item->get_properties( 'url' );
224             # To get all "p-name" properties:
225             $names = $item->get_properties( 'name' );
226              
227             Returns a list reference of all property values identified by the given
228             key. Values can be strings, unblessed references, or more item objects.
229              
230             Note that Microformats2 stores its properties' keys without their
231             prefixes, so that's how you should query for them here. In order words,
232             pass in "name" or "url" as an argument, not "p-name" or "u-url".
233              
234             =head3 get_property
235              
236             $property_value = $item->get_property( $property_key );
237              
238             # To get the first (and maybe only?) "u-url" property of this item:
239             $url = $item->get_property( 'url' );
240             # To get its "p-name" property:
241             $name = $item->get_property( 'name' );
242              
243             Like L<"get_properties">, but returns only the first property value identified
244             by the given key.
245              
246             If this item contains more than one such value, this will also emit a warning.
247              
248             =head3 value
249              
250             $value = $item->value;
251              
252             Returns the special C<value> attribute, if this item has it defined.
253              
254             =head3 all_types
255              
256             my @types = $item->all_types;
257             # Returns e.g. ( 'h-org', 'h-card' )
258              
259             my @short_types = $item->all_types( no_prefixes => 1 );
260             # Returns e.g. ( 'org', 'card' )
261              
262             Returns a list of all the types that this item identifies as.
263             Guaranteed to contain at least one value.
264              
265             Takes an argument hash, which recognizes the following single key:
266              
267             =over
268              
269             =item no_prefixes
270              
271             If set to a true value, then this object will remove the prefixes from
272             the list of item types before returning it to you. Practically speaking,
273             this means that it will remove the leading C<h-> from every type.
274              
275             =back
276              
277             =head3 has_type
278              
279             $bool = $item->has_type( $type )
280              
281             Returns true if the item claims to be of the given type, false
282             otherwise. (The argument can include a prefix, so e.g. both "entry" and
283             "h-entry" return the same result here.)
284              
285             =head3 parent
286              
287             $parent = $item->parent;
288              
289             Returns this item's parent item, if set.
290              
291             =head3 children
292              
293             $children_ref = $item->children;
294              
295             Returns a list reference of child items.
296              
297             =head1 AUTHOR
298              
299             Jason McIntosh (jmac@jmac.org)
300              
301             =head1 COPYRIGHT AND LICENSE
302              
303             This software is Copyright (c) 2018 by Jason McIntosh.
304              
305             This is free software, licensed under:
306              
307             The MIT (X11) License