File Coverage

blib/lib/Rubric/Entry.pm
Criterion Covered Total %
statement 62 62 100.0
branch 14 14 100.0
condition 4 6 66.6
subroutine 20 20 100.0
pod 8 9 88.8
total 108 111 97.3


line stmt bran cond sub pod time code
1 12     12   7087 use strict;
  12         22  
  12         291  
2 12     12   46 use warnings;
  12         16  
  12         442  
3             # ABSTRACT: a single entry made by a user
4              
5             use parent qw(Rubric::DBI);
6 12     12   52  
  12         17  
  12         66  
7             use Class::DBI::utf8;
8 12     12   8226  
  12         104736  
  12         48  
9             #pod =head1 DESCRIPTION
10             #pod
11             #pod This class provides an interface to Rubric entries. It inherits from
12             #pod Rubric::DBI, which is a Class::DBI class.
13             #pod
14             #pod =cut
15              
16             use Encode 2 qw(_utf8_on);
17 12     12   1334 use Rubric::Entry::Formatter;
  12         163  
  12         369  
18 12     12   4047 use String::TagString;
  12         27  
  12         256  
19 12     12   3236 use Time::Piece;
  12         177055  
  12         354  
20 12     12   11004  
  12         79188  
  12         60  
21             __PACKAGE__->table('entries');
22              
23             #pod =head1 COLUMNS
24             #pod
25             #pod id - a unique identifier
26             #pod link - the link to which the entry refers
27             #pod username - the user who made the entry
28             #pod title - the title of the link's destination
29             #pod description - a short description of the entry
30             #pod body - a long body of text for the entry
31             #pod created - the time when the entry was first created
32             #pod modified - the time when the entry was last modified
33             #pod
34             #pod =cut
35              
36             __PACKAGE__->columns(
37             All => qw(id link username title description body created modified)
38             );
39              
40             __PACKAGE__->utf8_columns(qw( title description body ));
41              
42             #pod =head1 RELATIONSHIPS
43             #pod
44             #pod =head2 link
45             #pod
46             #pod The link attribute returns a Rubric::Link.
47             #pod
48             #pod =cut
49              
50             __PACKAGE__->has_a(link => 'Rubric::Link');
51              
52             #pod =head2 uri
53             #pod
54             #pod The uri attribute returns the URI of the entry's link.
55             #pod
56             #pod =cut
57              
58              
59 4 100   4 1 1418 #pod =head2 username
  4         13  
  2         383  
60             #pod
61             #pod The user attribute returns a Rubric::User.
62             #pod
63             #pod =cut
64              
65             __PACKAGE__->has_a(username => 'Rubric::User');
66              
67             #pod =head2 tags
68             #pod
69             #pod Every entry has_many tags that describe it. The C<tags> method will return the
70             #pod tags, and the C<entrytags> method will return the Rubric::EntryTag objects that
71             #pod represent them.
72             #pod
73             #pod =cut
74              
75             __PACKAGE__->has_many(entrytags => 'Rubric::EntryTag');
76             __PACKAGE__->has_many(tags => [ 'Rubric::EntryTag' => 'tag' ]);
77              
78             #pod =head3 recent_tags_counted
79             #pod
80             #pod This method returns a reference to an array of arrayrefs, each a (tag, count)
81             #pod pair for tags used on the week's 50 most recent entries.
82             #pod
83             #pod =cut
84              
85             __PACKAGE__->set_sql(recent_tags_counted => <<'');
86             SELECT tag, COUNT(*) as count
87             FROM entrytags
88             WHERE entry IN (SELECT id FROM entries WHERE created > ? LIMIT 100)
89             AND tag NOT LIKE '@%%'
90             AND entry NOT IN (SELECT entry FROM entrytags WHERE tag = '@private')
91             GROUP BY tag
92             ORDER BY count DESC
93             LIMIT 50
94              
95             my ($class) = @_;
96             my $sth = $class->sql_recent_tags_counted;
97             $sth->execute(time - (86400 * 7));
98 11     11 1 1571 my $result = $sth->fetchall_arrayref;
99 11         72 return $result;
100 11         15900 }
101 11         4190  
102 11         67 #pod =head1 INFLATIONS
103             #pod
104             #pod =head2 created
105             #pod
106             #pod =head2 modified
107             #pod
108             #pod The created and modified columns are stored as seconds since epoch, but
109             #pod inflated to Time::Piece objects.
110             #pod
111             #pod =cut
112              
113             __PACKAGE__->has_a(
114             $_ => 'Time::Piece',
115             deflate => 'epoch',
116             inflate => Rubric::Config->display_localtime ? sub { localtime($_[0]) }
117             : sub { gmtime($_[0]) }
118             ) for qw(created modified);
119              
120             __PACKAGE__->add_trigger(before_create => \&_default_title);
121              
122             __PACKAGE__->add_trigger(before_create => \&_create_times);
123             __PACKAGE__->add_trigger(before_update => \&_update_times);
124              
125             my $self = shift;
126             $self->title('(default)') unless $self->{title}
127             }
128              
129 12     12   32278 my $self = shift;
130             $self->created(scalar gmtime) unless defined $self->{created};
131 12 100       77 $self->modified(scalar gmtime) unless defined $self->{modified};
132             }
133              
134 12     12   3381 my $self = shift;
135 12 100       72 $self->modified(scalar gmtime);
136 12 100       5526 }
137              
138             #pod =head1 METHODS
139             #pod
140 29     29   4433 #pod =head2 query(\%arg)
141 29         232 #pod
142             #pod The arguments to C<query> provide a set of abstract constraints for the query.
143             #pod These are sent to Rubric::Entry::Query, which builds an SQL query and returns
144             #pod the result of running it. (Either a list or an Iterator is returned.)
145             #pod
146             #pod (The built-in Class::DBI search method can't handle this kind of search.)
147             #pod
148             #pod user - entries for this User
149             #pod tags - entries with these tags (arrayref)
150             #pod link - entries for this Link
151             #pod urimd5 - entries for the Link with this md5 sum
152             #pod has_body - whether entries must have bodies (T, F, or undef)
153             #pod has_link - whether entries must have a link (T, F, or undef)
154             #pod (time spec) - {created,modified}_{before,after,on}
155             #pod limits entries by time; given as a complete or partial
156             #pod time and date string in the form "YYYY-MM-DD HH:MM"
157             #pod
158             #pod =cut
159              
160             my $self = shift;
161             require Rubric::Entry::Query;
162             Rubric::Entry::Query->query(@_);
163             }
164              
165             #pod =head2 set_new_tags(\%tags)
166             #pod
167 47     47 1 31816 #pod This method replaces all entry's current tags with the new set of tags.
168 47         1016 #pod
169 47         309 #pod =cut
170              
171             my ($self, $tags) = @_;
172             $self->entrytags->delete_all;
173             $self->update;
174              
175             while (my ($tag, $value) = each %$tags) {
176             $self->add_to_tags({ tag => $tag, tag_value => $value });
177             }
178             }
179 13     13 1 790  
180 13         60 #pod =head2 tags_from_string
181 13         15678 #pod
182             #pod my $tags = Rubric::Entry->tags_from_string($string);
183 13         19329 #pod
184 17         246166 #pod This (class) method takes a string of tags, delimited by whitespace, and
185             #pod returns an array of the tags, throwing an exception if it finds invalid tags.
186             #pod
187             #pod Valid tags (shouldn't this be documented somewhere else instead?) may contain
188             #pod letters, numbers, underscores, colons, dots, and asterisks. Hyphens me be
189             #pod used, but not as the first character.
190             #pod
191             #pod =cut
192              
193             my ($class, $tagstring) = @_;
194              
195             return {} unless $tagstring and $tagstring =~ /\S/;
196              
197             String::TagString->tags_from_string($tagstring);
198             }
199              
200             #pod =head2 C< markup >
201             #pod
202 35     35 1 34359 #pod This method returns the value of the entry's @markup tag, or C<_default> if
203             #pod there is no such tag.
204 35 100 66     302 #pod
205             #pod =cut
206 29         225  
207             my ($self) = @_;
208              
209             my ($tag)
210             = Rubric::EntryTag->search({ entry => $self->id, tag => '@markup' });
211              
212             return ($tag and $tag->tag_value) ? $tag->tag_value : '_default';
213             }
214              
215              
216             #pod =head2 C< body_as >
217 20     20 1 33 #pod
218             #pod my $formatted_body = $entry->body_as("html");
219 20         49 #pod
220             #pod This method returns the body of the entry, formatted into the given format. If
221             #pod the entry cannot be rendered into the given format, an exception is thrown.
222 20 100 66     14844 #pod
223             #pod =cut
224              
225             my ($self, $format) = @_;
226              
227             my $markup = $self->markup;
228              
229             Rubric::Entry::Formatter->format({
230             text => $self->body,
231             markup => $markup,
232             format => $format
233             });
234             }
235              
236 18     18 1 17176 my ($class, $field) = @_;
237              
238 18         34 return 'user' if $field eq 'username';
239              
240 18         2625 return $field;
241             }
242              
243             ## return retrieve_all'd objects in recent-to-older order
244              
245             __PACKAGE__->set_sql(RetrieveAll => <<'');
246             SELECT __ESSENTIAL__
247             FROM __TABLE__
248 96     96 1 25877 ORDER BY created DESC
249              
250 96 100       196 my ($self) = @_;
251             String::TagString->string_from_tags({
252 84         1557 map {; $_->tag => $_->tag_value } $self->entrytags
253             });
254             }
255              
256             1;
257              
258              
259             =pod
260              
261             =encoding UTF-8
262              
263 1     1 0 17 =head1 NAME
264              
265 1         5 Rubric::Entry - a single entry made by a user
  1         855  
266              
267             =head1 VERSION
268              
269             version 0.157
270              
271             =head1 DESCRIPTION
272              
273             This class provides an interface to Rubric entries. It inherits from
274             Rubric::DBI, which is a Class::DBI class.
275              
276             =head1 PERL VERSION
277              
278             This code is effectively abandonware. Although releases will sometimes be made
279             to update contact info or to fix packaging flaws, bug reports will mostly be
280             ignored. Feature requests are even more likely to be ignored. (If someone
281             takes up maintenance of this code, they will presumably remove this notice.)
282             This means that whatever version of perl is currently required is unlikely to
283             change -- but also that it might change at any new maintainer's whim.
284              
285             =head1 COLUMNS
286              
287             id - a unique identifier
288             link - the link to which the entry refers
289             username - the user who made the entry
290             title - the title of the link's destination
291             description - a short description of the entry
292             body - a long body of text for the entry
293             created - the time when the entry was first created
294             modified - the time when the entry was last modified
295              
296             =head1 RELATIONSHIPS
297              
298             =head2 link
299              
300             The link attribute returns a Rubric::Link.
301              
302             =head2 uri
303              
304             The uri attribute returns the URI of the entry's link.
305              
306             =head2 username
307              
308             The user attribute returns a Rubric::User.
309              
310             =head2 tags
311              
312             Every entry has_many tags that describe it. The C<tags> method will return the
313             tags, and the C<entrytags> method will return the Rubric::EntryTag objects that
314             represent them.
315              
316             =head3 recent_tags_counted
317              
318             This method returns a reference to an array of arrayrefs, each a (tag, count)
319             pair for tags used on the week's 50 most recent entries.
320              
321             =head1 INFLATIONS
322              
323             =head2 created
324              
325             =head2 modified
326              
327             The created and modified columns are stored as seconds since epoch, but
328             inflated to Time::Piece objects.
329              
330             =head1 METHODS
331              
332             =head2 query(\%arg)
333              
334             The arguments to C<query> provide a set of abstract constraints for the query.
335             These are sent to Rubric::Entry::Query, which builds an SQL query and returns
336             the result of running it. (Either a list or an Iterator is returned.)
337              
338             (The built-in Class::DBI search method can't handle this kind of search.)
339              
340             user - entries for this User
341             tags - entries with these tags (arrayref)
342             link - entries for this Link
343             urimd5 - entries for the Link with this md5 sum
344             has_body - whether entries must have bodies (T, F, or undef)
345             has_link - whether entries must have a link (T, F, or undef)
346             (time spec) - {created,modified}_{before,after,on}
347             limits entries by time; given as a complete or partial
348             time and date string in the form "YYYY-MM-DD HH:MM"
349              
350             =head2 set_new_tags(\%tags)
351              
352             This method replaces all entry's current tags with the new set of tags.
353              
354             =head2 tags_from_string
355              
356             my $tags = Rubric::Entry->tags_from_string($string);
357              
358             This (class) method takes a string of tags, delimited by whitespace, and
359             returns an array of the tags, throwing an exception if it finds invalid tags.
360              
361             Valid tags (shouldn't this be documented somewhere else instead?) may contain
362             letters, numbers, underscores, colons, dots, and asterisks. Hyphens me be
363             used, but not as the first character.
364              
365             =head2 C< markup >
366              
367             This method returns the value of the entry's @markup tag, or C<_default> if
368             there is no such tag.
369              
370             =head2 C< body_as >
371              
372             my $formatted_body = $entry->body_as("html");
373              
374             This method returns the body of the entry, formatted into the given format. If
375             the entry cannot be rendered into the given format, an exception is thrown.
376              
377             =head1 AUTHOR
378              
379             Ricardo SIGNES <rjbs@semiotic.systems>
380              
381             =head1 COPYRIGHT AND LICENSE
382              
383             This software is copyright (c) 2004 by Ricardo SIGNES.
384              
385             This is free software; you can redistribute it and/or modify it under
386             the same terms as the Perl 5 programming language system itself.
387              
388             =cut