File Coverage

blib/lib/MooX/JSON_LD.pm
Criterion Covered Total %
statement 55 55 100.0
branch 8 14 57.1
condition 7 10 70.0
subroutine 14 14 100.0
pod n/a
total 84 93 90.3


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             MooX::JSON_LD - Extend Moo to provide JSON-LD mark-up for your objects.
4              
5             =head1 SYNOPSIS
6              
7             # Your Moo (or Moose) Class
8             package::My::Moo::Class
9              
10             use Moo;
11              
12             use MooX::JSON_LD 'Person';
13              
14             has first_name => ( ... json_ld => 1 );
15             has last_name => ( ... json_ld => 1 );
16              
17             has birth_date => ( ...
18             json_ld => 'birthDate',
19             json_ld_serializer => sub { shift->birth_date->ymd },
20             );
21              
22             # Then, in a program somewhere...
23             use My::Moo::Class;
24              
25             my $obj = My::Moo::Class->new({
26             first_name => 'David',
27             last_name => 'Bowie',
28             birth_date => '1947-01-08',
29             });
30              
31             # print a text representation of the JSON-LD
32             print $obj->json_ld;
33              
34             # print the raw data structure for the JSON-LD
35             use Data::Dumper;
36             print Dumper $obj->json_ld_data;
37              
38             =head1 DESCRIPTION
39              
40             This is a companion module for L<MooX::Role::JSON_LD>. It extends the
41             C<has> method to support options to add attributes to the
42             C<json_ld_fields> and create the C<json_ld_type> .
43              
44             To declare the type, add it as the option when importing the module,
45             e.g.
46              
47             use MooX::JSON_LD 'Thing';
48              
49             Moo attributes are extended with the following options:
50              
51             =over
52              
53             =item C<json_ld>
54              
55             has headline => (
56             is => 'ro',
57             json_ld => 1,
58             );
59              
60             This adds the "headline" attribute to the C<json_ld_fields>.
61              
62             has alt_headline => (
63             is => 'ro',
64             json_ld => 'alternateHeadline',
65             );
66              
67             This adds the "alt_headline" attribute to the C<json_ld_fields>, with
68             the label "alternateHeadline".
69              
70             =item C<json_ld_serializer>
71              
72             has birth_date => (
73             is => 'ro',
74             isa => InstanceOf['DateTime'],
75             json_ld => 'birthDate',
76             json_ld_serializer => sub { shift->birth_date->ymd },
77             );
78              
79             This allows you to specify a method for converting the data into an
80             object that L<JSON> can serialize.
81              
82             =back
83              
84             =head1 AUTHOR
85              
86             Robert Rothenberg <rrwo@cpan.org>
87              
88             =head1 SEE ALSO
89              
90             L<MooX::Role::JSON_LD>
91              
92             =head1 COPYRIGHT AND LICENSE
93              
94             Copyright (C) 2018, Robert Rothenberg. All Rights Reserved.
95              
96             This script is free software; you can redistribute it and/or modify it
97             under the same terms as Perl itself.
98              
99              
100             =cut
101              
102             package MooX::JSON_LD;
103              
104 5     5   414859 use strict;
  5         27  
  5         130  
105 5     5   23 use warnings;
  5         7  
  5         96  
106              
107 5     5   19 use Moo ();
  5         7  
  5         69  
108 5     5   1993 use Moo::Role ();
  5         34519  
  5         101  
109              
110 5     5   1957 use MRO::Compat;
  5         7080  
  5         437  
111 5     5   37 use List::Util qw/ all /;
  5         9  
  5         487  
112 5     5   2008 use Sub::Quote qw/ quote_sub /;
  5         19631  
  5         356  
113              
114             our $VERSION = '0.0.17';
115              
116             my %Attributes;
117              
118             sub import {
119 8     8   30218 my ( $class, $type ) = @_;
120              
121 8         18 my $target = caller;
122              
123 5     5   30 no strict 'refs';
  5         9  
  5         116  
124 5     5   21 no warnings 'redefine';
  5         9  
  5         1678  
125              
126 8 50       85 my $installer =
127             $target->isa("Moo::Object")
128             ? \&Moo::_install_tracked
129             : \&Moo::Role::_install_tracked;
130              
131 8 50       58 if ( my $has = $target->can('has') ) {
132             my $new_has = sub {
133 16     16   57408 $has->( _process_has(@_) );
134 8         29 };
135 8         27 $installer->( $target, "has", $new_has );
136             }
137              
138 8 50       238 if ( defined $type ) {
139 8         37 quote_sub "${target}::json_ld_type", "'${type}'";
140             }
141              
142 8         817 my $name = "json_ld_fields";
143              
144             quote_sub "${target}::${name}", '$code->(@_)',
145             {
146             '$code' => \sub {
147 25     25   228 my ($self) = @_;
148 25   100     69 my $fields = $self->maybe::next::method || [];
149             return [
150 25         39 @{$fields},
151 25 50       271 @{$Attributes{$target} || []}
  25         98  
152             ];
153             },
154             }, {
155 8         65 no_defer => 1,
156             package => $target,
157             };
158              
159              
160 8 50   8   3582 unless ( all { $target->can($_) }
  8         65  
161             qw/ json_ld_encoder json_ld_data json_ld / )
162             {
163              
164 8         53 Moo::Role->apply_single_role_to_package( $target,
165             'MooX::Role::JSON_LD' );
166              
167             }
168              
169             }
170              
171             sub _process_has {
172 16     16   62 my ( $name, %opts ) = @_;
173              
174 16 50 33     58 if ( $opts{json_ld} || $opts{json_ld_serializer} ) {
175              
176 16         34 my $class = caller(1);
177 16   100     66 $Attributes{$class} ||= [];
178              
179 16         27 my $label = delete $opts{json_ld};
180 16         38 my $method = delete $opts{json_ld_serializer};
181              
182 16 100 66     23 push @{ $Attributes{$class} }, {
  16         102  
183             $label eq "1" ? $name : $label => $method || $name
184             };
185             }
186              
187 16         74 return ( $name, %opts );
188             }
189              
190             1;