File Coverage

blib/lib/Net/PMP/Profile.pm
Criterion Covered Total %
statement 41 44 93.1
branch 12 16 75.0
condition n/a
subroutine 9 9 100.0
pod 3 3 100.0
total 65 72 90.2


line stmt bran cond sub pod time code
1             package Net::PMP::Profile;
2 2     2   54038 use Moose;
  2         386263  
  2         18  
3 2     2   15446 use Data::Dump qw( dump );
  2         4035  
  2         115  
4 2     2   608 use Data::Clean::JSON;
  2         7308  
  2         81  
5 2     2   610 use Net::PMP::Profile::TypeConstraints;
  2         26  
  2         99  
6 2     2   879 use Net::PMP::CollectionDoc;
  2         576977  
  2         86  
7 2     2   17 use Net::PMP::CollectionDoc::Link;
  2         4  
  2         1041  
8              
9             our $VERSION = '0.102';
10              
11             # attributes
12             has 'title' => ( is => 'rw', isa => 'Str', required => 1, );
13             has 'hreflang' =>
14             ( is => 'rw', isa => 'Net::PMP::Type::ISO6391', default => sub {'en'}, );
15             has 'published' =>
16             ( is => 'rw', isa => 'Net::PMP::Type::DateTimeOrStr', coerce => 1, );
17             has 'valid' =>
18             ( is => 'rw', isa => 'Net::PMP::Type::ValidDates', coerce => 1, );
19             has 'tags' => (
20             is => 'rw',
21             isa => 'ArrayRef[Str]',
22             traits => ['Array'],
23             handles => { add_tag => 'push', },
24             );
25             has 'itags' => (
26             is => 'rw',
27             isa => 'ArrayRef[Str]',
28             traits => ['Array'],
29             handles => { add_itag => 'push', },
30             );
31             has 'description' => ( is => 'rw', isa => 'Str', );
32             has 'byline' => ( is => 'rw', isa => 'Str', );
33             has 'guid' => ( is => 'rw', isa => 'Net::PMP::Type::GUID', );
34             has 'href' => ( is => 'rw', isa => 'Net::PMP::Type::Href', coerce => 1 );
35              
36             # links
37             has 'author' => ( is => 'rw', isa => 'Net::PMP::Type::Links', coerce => 1, );
38             has 'copyright' =>
39             ( is => 'rw', isa => 'Net::PMP::Type::Links', coerce => 1, );
40             has 'distributor' =>
41             ( is => 'rw', isa => 'Net::PMP::Type::Links', coerce => 1, );
42             has 'profile' => ( is => 'rw', isa => 'Net::PMP::Type::Links', coerce => 1, );
43             has 'collection' =>
44             ( is => 'rw', isa => 'Net::PMP::Type::Links', coerce => 1, );
45             has 'item' => ( is => 'rw', isa => 'Net::PMP::Type::Links', coerce => 1, );
46             has 'permission' =>
47             ( is => 'rw', isa => 'Net::PMP::Type::Permissions', coerce => 1, );
48             has 'alternate' =>
49             ( is => 'rw', isa => 'Net::PMP::Type::Links', coerce => 1, );
50              
51 3     3 1 10 sub get_profile_url {'https://api.pmp.io/profiles/base'}
52 5     5 1 166 sub get_profile_title { ref(shift) }
53              
54             # singleton for class
55             my $cleaner = Data::Clean::JSON->new(
56             DateTime => [ call_method => 'stringify' ],
57             'Net::PMP::CollectionDoc::Link' => [ call_method => 'as_hash' ],
58             'Net::PMP::CollectionDoc::Permission' => [ call_method => 'as_hash' ],
59             SCALAR => ['deref_scalar'],
60             '-ref' => ['replace_with_ref'],
61             '-circular' => 0, #['detect_circular'],
62             '-obj' => ['unbless'],
63             );
64              
65             sub as_doc {
66 5     5 1 2195 my $self = shift;
67              
68             # coerce into hash
69 5         8 my %attrs = %{$self};
  5         32  
70              
71             # pull out those attributes which are really links
72 5         28 my %links = (
73             profile => [
74             Net::PMP::CollectionDoc::Link->new(
75             href => $self->get_profile_url,
76             title => $self->get_profile_title,
77             )
78             ]
79             );
80              
81 5         1644 my %class_attrs = map { $_->name => $_ } $self->meta->get_all_attributes;
  93         629  
82              
83             # not an attribute, a top-level key.
84 5         18 my $href = delete $attrs{href};
85              
86 5         19 for my $k ( keys %attrs ) {
87 31 50       56 if ( exists $class_attrs{$k} ) {
88 31         35 my $attr = $class_attrs{$k};
89 31         77 my $isa = $attr->{isa};
90              
91             #warn "key $k => isa $isa";
92 31 100       99 if ( $isa eq 'Net::PMP::Type::Links' ) {
    50          
    100          
    50          
    100          
    50          
93 4         6 $links{$k} = delete $attrs{$k};
94             }
95             elsif ( $isa eq 'Net::PMP::Type::Link' ) {
96 0         0 $links{$k} = [ delete $attrs{$k} ];
97             }
98             elsif ( $isa eq 'Net::PMP::Type::Permissions' ) {
99 2         6 $links{$k} = delete $attrs{$k};
100             }
101             elsif ( $isa eq 'Net::PMP::Type::Permission' ) {
102 0         0 $links{$k} = [ delete $attrs{$k} ];
103             }
104             elsif ( $isa eq 'Net::PMP::Type::MediaEnclosures' ) {
105 2         5 $links{$k} = [ map { $_->as_hash } @{ delete $attrs{$k} } ];
  2         9  
  2         5  
106             }
107             elsif ( $isa eq 'Net::PMP::Type::MediaEnclosure' ) {
108 0         0 $links{$k} = [ delete( $attrs{$k} )->as_hash ];
109             }
110             }
111             }
112              
113             # CollectionDoc can only work with strings
114 5         16 my %doc = ( attributes => \%attrs, links => \%links );
115              
116             # only pass href if it is set
117 5 100       13 $doc{href} = $href if $href;
118              
119             # coerce everything into something CollectionDoc can handle.
120 5         30 my $clean = $cleaner->clean_in_place( \%doc );
121              
122 5         2706 return Net::PMP::CollectionDoc->new($clean);
123              
124             }
125              
126             __PACKAGE__->meta->make_immutable();
127              
128             1;
129              
130             __END__
131              
132             =head1 NAME
133              
134             Net::PMP::Profile - Base Content Profile for PMP CollectionDoc
135              
136             =head1 SYNOPSIS
137              
138             use Net::PMP;
139             use Net::PMP::Profile;
140              
141             # instantiate a client
142             my $client = Net::PMP->client(
143             host => $host,
144             id => $client_id,
145             secret => $client_secret,
146             );
147              
148             # get explicit guid. otherwise one will be created for you on save.
149             my $guid = Net::PMP::CollectionDoc->create_guid();
150             my $profile_doc = Net::PMP::Profile->new(
151             href => $client->uri_for_doc($guid),
152             guid => $guid,
153             title => 'I am A Title',
154             published => '2013-12-03T12:34:56.789Z',
155             valid => {
156             from => "2013-04-11T13:21:31.598Z",
157             to => "3013-04-11T13:21:31.598Z",
158             },
159             byline => 'By: John Writer and Nancy Author',
160             description => 'This is a summary of the document.',
161             tags => [qw( foo bar baz )],
162             itags => [qw( abc123 )],
163             hreflang => 'en', # ISO639-1 code
164             author => [qw( http://api.pmp.io/user/some-guid )],
165             copyright => [qw( http://americanpublicmedia.org/ )],
166             distributor => [qw( http://api.pmp.io/organization/different-guid )],
167             );
168              
169             # save doc
170             $client->save($profile_doc);
171            
172             =cut
173              
174             =head1 DESCRIPTION
175              
176             Net::PMP::Profile implements the CollectionDoc fields for the PMP Base Content Profile
177             L<https://github.com/publicmediaplatform/pmpdocs/wiki/Base-Content-Profile>.
178              
179             This class B<does not> inherit from L<Net::PMP::CollectionDoc>. Net::PMP::Profile-based
180             classes are intended to ease data synchronization between PMP and other systems, by
181             providing client-based attribute validation and syntactic sugar. A CollectionDoc-based
182             object has no inherent validation for its attributes; it simply reflects what is on
183             the PMP server. A Profile-based object can be used to validate attribute values before
184             they are sent to the PMP server. The B<as_doc> method converts the Profile-based object
185             to a CollectionDoc-based object.
186              
187             =head1 METHODS
188              
189             =head2 title
190              
191             =head2 hreflang
192              
193             =head2 valid
194              
195             =head2 published
196              
197             Optional ISO 8601 datetime string. You may pass in a DateTime object and as_doc()
198             will render it correctly.
199              
200             =head2 byline
201              
202             Optional attribution string.
203              
204             =head2 description
205              
206             Optional summary string.
207              
208             =head2 tags
209              
210             Optional keyword array of strings.
211              
212             =head2 itags
213              
214             Optional array of strings for "internal" tags.
215              
216             =head2 add_tag( I<tagname> )
217              
218             Push I<tagname> onto the array.
219              
220             =head2 add_itag( I<tagname> )
221              
222             Push I<tagname> onto the array.
223              
224             =head2 as_doc
225              
226             Returns a L<Net::PMP::CollectionDoc> object suitable for L<Net::PMP::Client> interaction.
227              
228             =head2 get_profile_url
229              
230             Returns a string for the PMP profile's URL.
231              
232             =head2 get_profile_title
233              
234             Returns a string for the PMP profile's title. Default is the class name.
235              
236             =head1 AUTHOR
237              
238             Peter Karman, C<< <karman at cpan.org> >>
239              
240             =head1 BUGS
241              
242             Please report any bugs or feature requests to C<bug-net-pmp at rt.cpan.org>, or through
243             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-PMP-Profile>. I will be notified, and then you'll
244             automatically be notified of progress on your bug as I make changes.
245              
246              
247             =head1 SUPPORT
248              
249             You can find documentation for this module with the perldoc command.
250              
251             perldoc Net::PMP
252              
253              
254             You can also look for information at:
255              
256             =over 4
257              
258             =item IRC
259              
260             Join #pmp on L<http://freenode.net>.
261              
262             =item RT: CPAN's request tracker (report bugs here)
263              
264             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-PMP-Profile>
265              
266             =item AnnoCPAN: Annotated CPAN documentation
267              
268             L<http://annocpan.org/dist/Net-PMP-Profile>
269              
270             =item CPAN Ratings
271              
272             L<http://cpanratings.perl.org/d/Net-PMP-Profile>
273              
274             =item Search CPAN
275              
276             L<http://search.cpan.org/dist/Net-PMP-Profile/>
277              
278             =back
279              
280              
281             =head1 ACKNOWLEDGEMENTS
282              
283             American Public Media and the Public Media Platform sponsored the development of this module.
284              
285             =head1 LICENSE AND COPYRIGHT
286              
287             Copyright 2013 American Public Media Group
288              
289             See the LICENSE file that accompanies this module.
290              
291             =cut