add RTx::Calendar 0.07
[freeside.git] / rt / lib / RTx / Calendar.pm
1 package RTx::Calendar;
2
3 use strict;
4 use DateTime;
5 use DateTime::Set;
6
7 our $VERSION = "0.07";
8
9 sub FirstMonday {
10     my ($year, $month) = (shift, shift);
11     my $set = DateTime::Set->from_recurrence(
12         next => sub { $_[0]->truncate( to => 'day' )->subtract( days => 1 ) }
13     );
14
15     my $day = DateTime->new( year => $year, month => $month );
16
17     $day = $set->next($day) while $day->day_of_week != 1;
18     $day;
19
20 }
21
22 sub LastSunday {
23     my ($year, $month) = (shift, shift);
24     my $set = DateTime::Set->from_recurrence(
25         next => sub { $_[0]->truncate( to => 'day' )->add( days => 1 ) }
26     );
27
28     my $day = DateTime->last_day_of_month( year => $year, month => $month );
29
30     $day = $set->next($day) while $day->day_of_week != 7;
31     $day;
32 }
33
34 # we can't use RT::Date::Date because it uses gmtime
35 # and we need localtime
36 sub LocalDate {
37   my $ts = shift;
38   my ($d,$m,$y) = (localtime($ts))[3..5];
39   sprintf "%4d-%02d-%02d", ($y + 1900), ++$m, $d;
40 }
41
42 sub DatesClauses {
43     my ($Dates, $begin, $end) = @_;
44
45     my $clauses = "";
46
47     my @DateClauses = map {
48         "($_ >= '" . $begin . "' AND $_ <= '" . $end . "')"
49     } @$Dates;
50     $clauses  .= " AND " . " ( " . join(" OR ", @DateClauses) . " ) "
51         if @DateClauses;
52
53     return $clauses
54 }
55
56 sub FindTickets {
57     my ($CurrentUser, $Query, $Dates, $begin, $end) = @_;
58
59     $Query .= DatesClauses($Dates, $begin, $end)
60         if $begin and $end;
61
62     my $Tickets = RT::Tickets->new($CurrentUser);
63     $Tickets->FromSQL($Query);
64
65     my %Tickets;
66     my %AlreadySeen;
67
68     while ( my $Ticket = $Tickets->Next()) {
69
70         # How to find the LastContacted date ?
71         for my $Date (@$Dates) {
72             my $DateObj = $Date . "Obj";
73             push @{ $Tickets{ LocalDate($Ticket->$DateObj->Unix) } }, $Ticket
74                 # if reminder, check it's refering to a ticket
75                 unless ($Ticket->Type eq 'reminder' and not $Ticket->RefersTo->First)
76                     or $AlreadySeen{  LocalDate($Ticket->$DateObj->Unix) }{ $Ticket }++;
77         }
78     }
79     return %Tickets;
80 }
81
82
83 # Take a user object and return the search with Description "calendar" if it exists
84
85 sub SearchDefaultCalendar {
86     my $CurrentUser = shift;
87     my $Description = "calendar";
88
89     # I'm quite sure the loop isn't usefull but...
90     my @Objects = $CurrentUser->UserObj;
91     for my $object (@Objects) {
92         next unless ref($object) eq 'RT::User' && $object->id == $CurrentUser->Id;
93         my @searches = $object->Attributes->Named('SavedSearch');
94         for my $search (@searches) {
95             next if ($search->SubValue('SearchType')
96                          && $search->SubValue('SearchType') ne 'Ticket');
97
98             return $search
99                 if "calendar" eq $search->Description;
100         }
101     }
102 }
103
104
105 1;
106
107 __END__
108
109 =head1 NAME
110
111 RTx::Calendar - Calendar for RT due tasks
112
113 =head1 VERSION
114
115 This document describes version 0.07 of RTx::Calendar
116
117 =head1 DESCRIPTION
118
119 This RT extension provides a calendar view for your tickets and your
120 reminders so you see when is your next due ticket. You can find it in
121 the menu Search->Calendar.
122
123 There's a portlet to put on your home page (see Prefs/MyRT.html)
124
125 You can also enable ics (ICal) feeds for your default calendar and all
126 your private searches in Prefs/Calendar.html. Authentication is magic
127 number based so that you can give those feeds to other people.
128
129 You can find screenshots on
130 http://gaspard.mine.nu/dotclear/index.php?tag/rtx-calendar
131
132 =head1 INSTALLATION
133
134 If you upgrade from 0.02, see next part before.
135
136 You need to install those three modules :
137
138   * Date::ICal
139   * Data::ICal
140   * DateTime::Set
141
142 Install it like a standard perl module
143
144  perl Makefile.PL
145  make
146  make install
147
148 If your RT is not in the default path (/opt/rt3) you must set RTHOME
149 before doing the Makefile.PL
150
151 =head1 CONFIGURATION
152
153 =head2 Base configuration
154
155 In RT 3.8 and later, to enable calendar plugin, you must add something
156 like that in your etc/RT_SiteConfig.pm :
157
158   Set(@Plugins,(qw(RTx::Calendar)));
159
160 To use MyCalendar portlet you must add MyCalendar to
161 $HomepageComponents in etc/RT_SiteConfig.pm like that :
162
163   Set($HomepageComponents, [qw(QuickCreate Quicksearch MyCalendar
164      MyAdminQueues MySupportQueues MyReminders RefreshHomepage)]);
165
166 To enable private searches ICal feeds, you need to give
167 CreateSavedSearch and LoadSavedSearch rights to your users.
168
169 =head2 Display configuration
170
171 You can show the owner in each day box by adding this line to your
172 etc/RT_SiteConfig.pm :
173
174     Set($CalendarDisplayOwner, 1);
175
176 You can change which fields show up in the popup display when you
177 mouse over a date in etc/RT_SiteConfig.pm :
178
179     @CalendarPopupFields = ('Status', 'OwnerObj->Name', 'DueObj->ISO');
180
181 =head2 ICAL feed configuration
182
183 By default, tickets are todo and reminders event. You can change this
184 by setting $RT::ICalTicketType and $RT::ICalReminderType in etc/RT_SiteConfig.pm :
185
186   Set($ICalTicketType,   "Data::ICal::Entry::Event");
187   Set($ICalReminderType ,"Data::ICal::Entry::Todo");
188
189 =head1 USAGE
190
191 A small help section is available in /Prefs/Calendar.html
192
193 =head1 UPGRADE FROM 0.02
194
195 As I've change directory structure, if you upgrade from 0.02 you need
196 to delete old files manually. Go in RTHOME/share/html (by default
197 /opt/rt3/share/html) and delete those files :
198
199   rm -rf Callbacks/RTx-Calendar
200   rm Tools/Calendar.html
201
202 RTx-Calendar may work without this but it's not very clean.
203
204 =head1 BUGS
205
206 =over
207
208 =item *
209 compatible only with RT 3.6 for the moment. If someone need
210 compatibility with 3.4 I can work on this. And I will work on 3.7
211 compatibility later.
212
213 =back
214
215 =head1 AUTHORS
216
217 Nicolas Chuche E<lt>nchuche@barna.beE<gt>
218
219 Idea borrowed from redmine's calendar (Thanks Jean-Philippe).
220
221 =head1 COPYRIGHT
222
223 Copyright 2007 by Nicolas Chuche E<lt>nchuche@barna.beE<gt>
224
225 This program is free software; you can redistribute it and/or 
226 modify it under the same terms as Perl itself.
227
228 See L<http://www.perl.com/perl/misc/Artistic.html>
229
230 =cut