File Coverage

blib/lib/Labyrinth/Plugin/Articles/Diary.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             package Labyrinth::Plugin::Articles::Diary;
2              
3 5     5   85373 use warnings;
  5         9  
  5         159  
4 5     5   17 use strict;
  5         8  
  5         137  
5              
6 5     5   18 use vars qw($VERSION);
  5         10  
  5         319  
7             $VERSION = '1.06';
8              
9             =head1 NAME
10              
11             Labyrinth::Plugin::Articles::Diary - Diary plugin for Labyrinth framework
12              
13             =head1 DESCRIPTION
14              
15             Contains all the diary handling functionality for Labyrinth.
16              
17             =cut
18              
19             # -------------------------------------
20             # Library Modules
21              
22 5     5   22 use base qw(Labyrinth::Plugin::Articles);
  5         9  
  5         1787  
23              
24 5     5   2039 use Clone qw(clone);
  5         11181  
  5         333  
25 5     5   2363 use Time::Local;
  5         6740  
  5         287  
26             #use Data::Dumper;
27              
28 5     5   3210 use Labyrinth::Audit;
  0            
  0            
29             use Labyrinth::DBUtils;
30             use Labyrinth::DTUtils;
31             use Labyrinth::Globals;
32             use Labyrinth::IPAddr;
33             use Labyrinth::Metadata;
34             use Labyrinth::MLUtils;
35             use Labyrinth::Session;
36             use Labyrinth::Support;
37             use Labyrinth::Variables;
38             use Labyrinth::Writer;
39              
40             # -------------------------------------
41             # Variables
42              
43             # type: 0 = optional, 1 = mandatory
44             # html: 0 = none, 1 = text, 2 = textarea
45              
46             my %fields = (
47             articleid => { type => 0, html => 0 },
48             quickname => { type => 1, html => 0 },
49             title => { type => 1, html => 1 },
50             );
51              
52             my (@mandatory,@allfields);
53             for(keys %fields) {
54             push @mandatory, $_ if($fields{$_}->{type});
55             push @allfields, $_;
56             }
57              
58             my $LEVEL = ADMIN;
59             my $SECTIONID = 6;
60              
61             my %cfields = (
62             articleid => { type => 0, html => 0 },
63             commentid => { type => 0, html => 0 },
64             subject => { type => 0, html => 1 },
65             body => { type => 1, html => 3 },
66             author => { type => 1, html => 1 },
67             href => { type => 0, html => 1 },
68             publish => { type => 0, html => 0 },
69             );
70              
71             my (@cmandatory,@callfields);
72             for(keys %cfields) {
73             push @cmandatory, $_ if($cfields{$_}->{type});
74             push @callfields, $_;
75             }
76              
77             my ($BLOCK,$ALLOW) = (1,2);
78              
79             # -------------------------------------
80             # Public Methods
81              
82             =head1 PUBLIC INTERFACE METHODS
83              
84             =over 4
85              
86             =item Archive
87              
88             Retrieves a list of archived diary entries
89              
90             =item Page
91              
92             Retrieves an set of diary entries, for a given page. Default to first page.
93              
94             =item List
95              
96             Retrieves an initial list of diary entries. Primarily used to prepare a front
97             page.
98              
99             =item Meta
100              
101             Retrieves a list of diary entries based on given meta tags.
102              
103             =item Search
104              
105             Retrieves a list of diary entries based on a given search string.
106              
107             =item Cloud
108              
109             Provides the current tag cloud.
110              
111             =item Item
112              
113             Provides a single diary entry.
114              
115             =item Comment
116              
117             Allow a user to submit a comment.
118              
119             =item LatestComments
120              
121             Retrieve the most recent comments, for use in a side panel or similar.
122              
123             =item Posted
124              
125             Number of posts posted by the given writer.
126              
127             =back
128              
129             =cut
130              
131             sub Archive {
132             my $oldid = $cgiparams{sectionid};
133             $cgiparams{sectionid} = $SECTIONID;
134             $cgiparams{section} = 'diary';
135              
136             shift->SUPER::Archive();
137             $tvars{articles} = undef;
138             $cgiparams{sectionid} = $oldid; # reset
139             }
140              
141             sub Page {
142             return List() if($cgiparams{volume}); # volumes need to be handled by the List function
143              
144             $cgiparams{sectionid} = $SECTIONID;
145             $settings{data}{article_pageset} = $settings{diary_pageset};
146              
147             shift->SUPER::Page();
148             _count_comments();
149             }
150              
151             sub List {
152             $cgiparams{sectionid} = $SECTIONID;
153             $settings{data}{article_limit} = $settings{diary_limit};
154             $settings{data}{article_stop} = $settings{diary_stop};
155              
156             if($cgiparams{volume}) {
157             $settings{where} = 'createdate > ' . _vol2date($cgiparams{volume}) .
158             ' AND createdate < ' . _vol2date($cgiparams{volume} + 1);
159             }
160              
161             shift->SUPER::List();
162             _count_comments();
163              
164             # see if we can do next and previous
165             my $this = 0;
166             if($cgiparams{volume}) {
167             for my $vol (@{$tvars{archive}{diary}}) {
168             if($cgiparams{volume} == $vol->{volumeid}) {
169             $this = 1;
170             } else {
171             $tvars{archive}{volumes}{prev} = $vol if(!$this);
172             $tvars{archive}{volumes}{next} ||= $vol if($this);
173             }
174             }
175             }
176             }
177              
178             sub Meta {
179             return unless($cgiparams{data});
180              
181             my $oldid = $cgiparams{sectionid};
182             $cgiparams{sectionid} = $SECTIONID;
183             $settings{data}{article_limit} = $settings{diary_limit};
184             $settings{data}{article_stop} = $settings{diary_stop};
185              
186             shift->SUPER::Meta();
187             _count_comments();
188             $cgiparams{sectionid} = $oldid; # reset
189             }
190              
191             sub Cloud {
192             my $oldid = $cgiparams{sectionid};
193             $cgiparams{sectionid} = $SECTIONID;
194             $cgiparams{actcode} = 'diary-meta';
195             shift->SUPER::Cloud();
196             $cgiparams{sectionid} = $oldid; # reset
197             }
198              
199             sub Search {
200             return unless($cgiparams{data});
201              
202             my $oldid = $cgiparams{sectionid};
203             $cgiparams{sectionid} = $SECTIONID;
204             $settings{data}{article_limit} = $settings{diary_limit};
205             $settings{data}{article_stop} = $settings{diary_stop};
206              
207             shift->SUPER::Search();
208             _count_comments();
209             $cgiparams{sectionid} = $oldid; # reset
210             }
211              
212             sub Item {
213             my $oldid = $cgiparams{sectionid};
214             $cgiparams{sectionid} = $SECTIONID;
215             shift->SUPER::Item();
216             $tvars{diary} = $tvars{article};
217             my @rows = $dbi->GetQuery('hash','GetDiaryComments',$tvars{diary}->{data}->{articleid});
218             for(@rows) {
219             $_->{postdate} = formatDate(6,$_->{createdate});
220             }
221              
222             $tvars{comments} = \@rows;
223             $cgiparams{sectionid} = $oldid; # reset
224             }
225              
226             sub Comment {
227             my $check = CheckIP();
228             if( $check == $BLOCK
229             || $cgiparams{typekey}
230             || !$cgiparams{loopback}
231             || $cgiparams{loopback} ne $settings{ipaddr}) {
232              
233             $tvars{thanks} = 3;
234             # print STDERR "COMMENT SPAM ALERT:\n" . Dumper(\%cgiparams);
235             return;
236             }
237              
238             $cgiparams{publish} = $check == $ALLOW ? 3 : 2;
239              
240             for(keys %cfields) {
241             next unless($cfields{$_});
242             if($cfields{$_}->{html} == 1) { $cgiparams{$_} = CleanHTML($cgiparams{$_}) }
243             elsif($cfields{$_}->{html} == 2) { $cgiparams{$_} = CleanTags($cgiparams{$_}) }
244             elsif($cfields{$_}->{html} == 3) { $cgiparams{$_} = CleanTags($cgiparams{$_}) }
245             }
246              
247             return if FieldCheck(\@callfields,\@cmandatory);
248              
249             if($tvars{data}->{subject} eq 'ARRAY(0x84fb748)') {
250             # print STDERR "COMMENT SPAM ALERT:\n" . Dumper(\%cgiparams);
251             $tvars{thanks} = 3;
252             return;
253             }
254              
255             my @fields = ( $tvars{data}->{articleid},
256             $tvars{data}->{subject},
257             formatDate(), # create date
258             $tvars{data}->{body},
259             $tvars{data}->{author},
260             $tvars{data}->{href},
261             $tvars{data}->{publish},
262             $settings{ipaddr}
263             );
264              
265             $dbi->IDQuery('AddComment',@fields);
266             $tvars{thanks} = $check == $ALLOW ? 2 : 1;
267             }
268              
269             sub LatestComments {
270             my @rows = $dbi->GetQuery('hash','GetCommentsLatest');
271             $tvars{latest}->{comments} = \@rows;
272             }
273              
274             sub Posted {
275             return unless($cgiparams{'userid'});
276             my @rows = $dbi->GetQuery('array','CountPosts',$cgiparams{'userid'});
277             $tvars{data}{posts} = @rows ? $rows[0]->[0] : 0;
278             }
279              
280             # -------------------------------------
281             # Admin Methods
282              
283             =head1 ADMIN INTERFACE METHODS
284              
285             =over 4
286              
287             =item Access
288              
289             Check whether user has the appropriate admin access.
290              
291             =item Admin
292              
293             Lists the current set of diary entries.
294              
295             Also provides the delete, copy and promote functionality from the main
296             administration page for the given section.
297              
298             =item Add
299              
300             Add a diary entry.
301              
302             =item Edit
303              
304             Edit a diary entry.
305              
306             =item Save
307              
308             Save a diary entry.
309              
310             =item Delete
311              
312             Delete a diary entry.
313              
314             =item ListComment
315              
316             List current unpublished comments.
317              
318             =item EditComment
319              
320             Edit a given comment.
321              
322             =item SaveComment
323              
324             Save a given comment.
325              
326             =item PromoteComment
327              
328             Promote a given comment.
329              
330             =item DeleteComment
331              
332             Delete a given comment.
333              
334             =item MarkIP
335              
336             Mark matching comments as appropriate. Actions are block and allow.
337              
338             =back
339              
340             =cut
341              
342             sub Access { Authorised($LEVEL) }
343              
344             sub Admin {
345             return unless AccessUser($LEVEL);
346             $cgiparams{sectionid} = $SECTIONID;
347             shift->SUPER::Admin();
348              
349             for my $article (@{ $tvars{data} }) {
350             my @rows = $dbi->GetQuery('array','CountDiaryComments',{ids => $article->{articleid}});
351             $article->{comments} = @rows ? $rows[0]->[1] : '';
352             }
353             }
354              
355             sub Add {
356             return unless AccessUser($LEVEL);
357             $cgiparams{sectionid} = $SECTIONID;
358             my $self = shift;
359             $self->SUPER::Add();
360             $self->SUPER::Tags();
361             }
362              
363             sub Edit {
364             return unless AccessUser($LEVEL);
365             $cgiparams{sectionid} = $SECTIONID;
366              
367             my $self = shift;
368             $self->SUPER::Edit();
369             $self->SUPER::Tags();
370             my @rows = $dbi->GetQuery('hash','GetDiaryComments',$tvars{article}->{data}->{articleid});
371             for(@rows) {
372             $_->{postdate} = formatDate(6,$_->{createdate});
373             }
374              
375             $tvars{articles}->{$tvars{primary}}->{data}{comments} = scalar(@rows);
376             $tvars{comments} = \@rows if(@rows);
377             }
378              
379             sub Save {
380             return unless AccessUser($LEVEL);
381             $cgiparams{sectionid} = $SECTIONID;
382             $cgiparams{quickname} = formatDate(0);
383             shift->SUPER::Save();
384             }
385              
386             sub Delete {
387             return unless AccessUser($LEVEL);
388             $cgiparams{sectionid} = $SECTIONID;
389             shift->SUPER::Delete();
390             }
391              
392             sub ListComment {
393             return unless AccessUser($LEVEL);
394              
395             my (@rows);
396             if($cgiparams{pattern}) {
397             @rows = $dbi->GetQuery('hash','GetCommentMatches','%'.$cgiparams{pattern}.'%');
398             for my $row (@rows) {
399             BlockIP($row->{author},$row->{ipaddr});
400             $dbi->DoQuery('DeleteComment',$row->{'commentid'});
401             }
402             }
403              
404             @rows = $dbi->GetQuery('hash','GetAdminCommentIDs');
405              
406             my $start = $cgiparams{start} || 1;
407             my $limit = $cgiparams{limit} || $settings{comment_limit} || 100;
408             my $last = int(scalar(@rows) / $limit);
409             my $max = scalar(@rows);
410              
411             LogDebug("start=$start, limit=$limit, last=$last, max=$max");
412              
413             if(@rows) {
414             my $count = ($start-1) * $limit;
415             splice(@rows,0,$count) if($count > 0);
416             splice(@rows,$limit) if(@rows > $limit);
417             my $ids = join(',',map {$_->{commentid}} @rows);
418              
419             @rows = $dbi->GetQuery('hash','GetAdminComments',{ ids => $ids });
420             for(@rows) {
421             $_->{postdate} = formatDate(17,$_->{createdate});
422             }
423              
424             $tvars{comments} = \@rows;
425             }
426              
427             my ($prev,$next) = ($start-1,$start+1);
428             $prev = 1 if($prev < 1);
429             $next = $last if($next > $last);
430              
431             $tvars{page}{prev} = $prev;
432             $tvars{page}{start} = $start;
433             $tvars{page}{next} = $next;
434             $tvars{page}{last} = $last;
435             $tvars{page}{limit} = $limit;
436             $tvars{page}{comments} = $max;
437              
438             my @offenders = $dbi->GetQuery('hash','WorstOffenders');
439             $tvars{offenders} = \@offenders if(@offenders);
440             }
441              
442             sub EditComment {
443             return unless AccessUser($LEVEL);
444             return unless AuthorCheck('GetCommentByID','commentid',$LEVEL);
445             $tvars{comment} = $tvars{data};
446             $tvars{comment}->{postdate} = formatDate(17,$tvars{comment}->{createdate});
447             $tvars{comment}->{ddpublish} = PublishSelect($tvars{comment}->{publish});
448             }
449              
450             sub SaveComment {
451             return unless AccessUser($LEVEL);
452             return unless AuthorCheck('GetCommentByID','commentid',$LEVEL);
453             for(keys %cfields) {
454             next unless($cfields{$_});
455             if($cfields{$_}->{html} == 1) { $cgiparams{$_} = CleanHTML($cgiparams{$_}) }
456             elsif($cfields{$_}->{html} == 2) { $cgiparams{$_} = CleanTags($cgiparams{$_}) }
457             elsif($cfields{$_}->{html} == 3) { $cgiparams{$_} = CleanTags($cgiparams{$_}) }
458             }
459              
460             return if FieldCheck(\@callfields,\@cmandatory);
461             $tvars{data}->{publish} ||= 1;
462              
463             my @fields = ( $tvars{data}->{subject},
464             $tvars{data}->{body},
465             $tvars{data}->{author},
466             $tvars{data}->{href},
467             $tvars{data}->{publish},
468             $tvars{data}->{commentid}
469             );
470              
471             $dbi->IDQuery('SaveComment',@fields);
472             }
473              
474             sub PromoteComment {
475             return unless AccessUser($LEVEL);
476             return unless AuthorCheck('GetCommentByID','commentid',$LEVEL);
477             $dbi->DoQuery('PromoteComment',$tvars{data}->{publish}+1,$cgiparams{'commentid'});
478             }
479              
480             sub DeleteComment {
481             return unless AccessUser($LEVEL);
482             return unless AuthorCheck('GetCommentByID','commentid',$LEVEL);
483             $dbi->DoQuery('DeleteComment',$cgiparams{'commentid'});
484             }
485              
486             sub MarkIP {
487             return unless AccessUser($LEVEL);
488             return unless AuthorCheck('GetCommentByID','commentid',$LEVEL);
489             return unless $cgiparams{mark};
490             my $mark = $cgiparams{mark} eq 'allow' ? 2 : 1;
491              
492             if($mark == 2) { AllowIP($tvars{data}->{author},$tvars{data}->{ipaddr}) }
493             else { BlockIP($tvars{data}->{author},$tvars{data}->{ipaddr}) }
494              
495             my @rows = $dbi->GetQuery('hash','GetAdminCommentByIP',$tvars{data}->{ipaddr});
496             for my $row (@rows) {
497             next unless($row->{ipaddr} eq $tvars{data}->{ipaddr});
498             if($mark == 2) {
499             $dbi->DoQuery('PromoteComment',$tvars{data}->{publish}+1,$row->{'commentid'});
500             } else {
501             $dbi->DoQuery('DeleteComment',$row->{'commentid'});
502             }
503             }
504             }
505              
506             # -------------------------------------
507             # Private Methods
508              
509             sub _count_comments {
510             my $type = shift || 'mainarts';
511             return unless($tvars{$type} && scalar(@{$tvars{$type}}));
512              
513             my $ids = join(',', map {$_->{data}{articleid}} @{$tvars{$type}});
514             my @rows = $dbi->GetQuery('array','CountDiaryComments',{ids => $ids});
515             my %rows = map {$_->[0] => $_->[1]} @rows;
516             for my $item (@{$tvars{$type}}) {
517             $item->{comments} = $rows{$item->{data}{articleid}} || 0;
518             }
519             }
520              
521             sub _vol2date {
522             my ($year,$mon) = $_[0] =~ /^(\d{4})(\d{2})/;
523             if($mon == 13) { $year++;$mon=1; }
524             return timegm(0,0,0,1,$mon-1,$year);
525             }
526              
527             1;
528              
529             __END__