Allow editing of booking texts
[infodrom.org/service.infodrom.org] / class / calendar.class.php
1 <?php
2
3 class Calendar extends DatabaseTable {
4
5   public function __construct($id=false)
6   {
7     $db = new Database(DBDRIVER, DBHOST, DAV_DBNAME, DBUSER, DBPASS);
8
9     parent::__construct('calendar_item', false, $db);
10   }
11
12   public static function pgTimestamp($timestamp)
13   {
14     if (is_string($timestamp))
15       return $timestamp;
16     elseif (is_int($timestamp))
17       return date('Y-m-d H:i:s', $timestamp);
18     elseif (is_object($timestamp) && is_a($timestamp, 'DateTime'))
19       return $timestamp->format('Y-m-d H:i:s');
20     else
21       return NULL;
22   }
23
24   public static function formatTimespan($dtstart, $dtend=false)
25   {
26     $start = new DateTime($dtstart);
27
28     if ($dtend !== false) {
29       $end = new DateTime($dtend);
30
31       if ($start->format('Y-m-d') == $end->format('Y-m-d')) {
32         if ($start->format('i') == '00' && $end->format('i') == '00')
33           return $start->format('d.m. H') . '-' . $end->format('H') . ' Uhr';
34         else
35           return $start->format('d.m. H:i') . '-' . $end->format('H:i');
36       }
37
38       if ($start->format('H:i:s') == '00:00:00' && $end->format('H:i:s') == '00:00:00') {
39         $end->sub(new DateInterval('P1D'));
40         if ($start->format('Y-m-d') == $end->format('Y-m-d'))
41           return $start->format('d.m.');
42         else
43           return $start->format('d.m.') . '-' . $end->format('d.m.');
44       }
45
46       if ($start->format('Y-m-') == $end->format('Y-m-')) {
47         return $start->format('d.m. H:i') . '-' . $end->format('d.m. H:i');
48       }
49     }
50
51     return 'timespan';
52   }
53
54   public function getYears()
55   {
56     $sql = sprintf("SELECT DISTINCT extract(year from dtstart) AS year FROM calendar_item WHERE user_no = %d ORDER BY year",
57                    DAV_USER_NO);
58     return $this->db->fetchObjectList($sql);
59   }
60
61   public function getItems($from=false, $to=false)
62   {
63     $sql = sprintf("SELECT dav_id,dtstart,dtend,EXTRACT(WEEK FROM dtstart) AS kw,summary,location,description FROM calendar_item WHERE user_no = %d",
64                    DAV_USER_NO);
65     if ($from)
66       $sql .= sprintf(" AND dtstart >= %s", $this->db->quote(self::pgTimestamp($from)));
67     if ($to)
68       $sql .= sprintf(" AND dtstart <= %s", $this->db->quote(self::pgTimestamp($to)));
69
70     $sql .= " ORDER BY dtstart";
71
72     return $this->db->fetchObjectList($sql);
73   }
74
75   public function ajaxMonths(Array $data)
76   {
77     $monthname = array('','Jan','Feb','Mär', 'Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez');
78     $sql = sprintf("SELECT DISTINCT extract(year from dtstart) AS year,extract(month from dtstart) AS month " .
79                    "FROM calendar_item WHERE user_no = %d ORDER BY year DESC,month DESC",
80                    DAV_USER_NO);
81     $out = '';
82     $now = array(date('Y'), date('m'));
83     foreach ($this->db->fetchObjectList($sql) as $row) {
84       $out .= sprintf('<option value="%04d-%02d"%s>%s %04d</option>',
85                       $row->year, $row->month,
86                       $row->year == $now[0] && $row->month == $now[1] ? ' selected' : '',
87                       utf8_encode($monthname[$row->month]), $row->year);
88     }
89
90     return array('values' => array('thismonth' => date('Y-m')),
91                  'html' => array('month' => $out));
92   }
93
94   private function getMonthData($year, $month)
95   {
96     $numdays = cal_days_in_month(CAL_GREGORIAN, $month, $year);
97
98     $areaDates = array();
99     for ($i=1; $i < 8; $i++) {
100       $date = sprintf('%04d-%02d-%02d', $year, $month, 1);
101       $sql = sprintf("SELECT dav_id FROM calendar_item WHERE user_no = %d AND dtstart::date = '%s'::date - INTERVAL '%d DAY' ORDER BY dtstart",
102                      DAV_USER_NO, $date, $i);
103       foreach ($this->fetchObjectList($sql) as $row) {
104         $item = new Calendar_Item($row->dav_id);
105         if ($item->isRegular()) continue;
106
107         foreach ($item->getDays() as $adate) {
108           if (!array_key_exists($adate, $areaDates))
109             $areaDates[$adate] = array();
110           $areaDates[$adate][] = $item;
111         }
112       }
113     }
114
115     $regDates = array();
116     for ($day=1; $day <= $numdays; $day++) {
117       $timestamp = mktime (0, 0, 0, $month, $day, $year);
118       $date = sprintf('%04d-%02d-%02d', $year, $month, $day);
119       $sql = sprintf("SELECT dav_id FROM calendar_item WHERE user_no = %d AND dtstart::date = '%s'::date ORDER BY dtstart",
120                      DAV_USER_NO, $date);
121
122       foreach ($this->fetchObjectList($sql) as $row) {
123         $item = new Calendar_Item($row->dav_id);
124
125         if (!$item->isRegular()) {
126           foreach ($item->getDays() as $adate) {
127             if (!array_key_exists($adate, $areaDates))
128               $areaDates[$adate] = array();
129             $areaDates[$adate][] = $item;
130           }
131         } else {
132           if (!array_key_exists($date, $regDates))
133             $regDates[$date] = array();
134           $regDates[$date][] = $item;
135         }
136       }
137     }
138
139     return array($areaDates, $regDates);
140   }
141
142   private function formatOneMonth($year, $month)
143   {
144     $weekday = array('', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So');
145     $monthname = array('','Jan','Feb','Mär', 'Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez');
146     $numdays = cal_days_in_month(CAL_GREGORIAN, $month, $year);
147
148     $out = sprintf('<div class="head" month="%04d-%02d">%s %04d</div>',
149                    $year, $month, $monthname[intval($month)], $year);
150
151     list($areaDates, $regDates) = $this->getMonthData($year, $month);
152
153     $today = date('Y-m-d');
154     for ($day=1; $day <= $numdays; $day++) {
155       $timestamp = mktime (0, 0, 0, $month, $day, $year);
156       $date = sprintf('%04d-%02d-%02d', $year, $month, $day);
157       $items = array();
158
159       if (array_key_exists($date, $areaDates))
160         foreach ($areaDates[$date] as $item)
161           $items[] = $item->toSpan();
162
163       if (array_key_exists($date, $regDates))
164         foreach ($regDates[$date] as $item)
165           $items[] = $item->toSpan();
166
167       $class = date('N', $timestamp) == 7 ? 'sunday' : 'day';
168       if ($today == $date) $class .= ' today';
169       $kw = date('N', $timestamp) == 1 ? sprintf('<div class="kw">%d</div>', date('W', $timestamp)) : '';
170       $out .= sprintf('<div class="%s" day="%d"><div class="wday">%s</div><div class="date">%d.</div>%s%s</div>',
171                       $class,
172                       $day,
173                       $weekday[intval(date('N', $timestamp))],
174                       $day,
175                       count($items) ? implode('', $items) : '&nbsp;',
176                       $kw);
177     }
178     return $out;
179   }
180
181   public function ajaxBiMonth(Array $data)
182   {
183     list($year, $month) = explode('-', $data['month']);
184     if (!empty($data['direction'])) {
185       switch ($data['direction']) {
186       case 'prev':
187         if ($month > 1) $month--;
188         else {$year--; $month = 12;}
189         break;
190       case 'next':
191         if ($month < 12) $month++;
192         else {$year++; $month = 1;}
193         break;
194       }
195     }
196
197     $monthStr = sprintf('%04d-%02d', $year, $month);
198     $right = $this->formatOneMonth($year, $month);
199
200     if ($month < 12) $month++;
201     else {$year++; $month = 1;}
202     $left = $this->formatOneMonth($year, $month);
203
204     $out = '<div class="bimonth">';
205
206     $out .= '<div class="monthcolumn">';
207     $out .= $right;
208     $out .= '</div>';
209
210     $out .= '<div class="monthcolumn">';
211     $out .= $left;
212     $out .= '</div>';
213
214     $out .= '</div>';
215
216     return array('values' => array('thismonth' => $monthStr),
217                  'html' => array('termine' => $out));
218   }
219
220   public function ajaxMonth(Array $data)
221   {
222     $monthname = array('','Januar','Februar','März', 'April','Mai','Juni','Juli','August','September','Oktober','November','Dezember');
223
224     list($year, $month) = explode('-', $data['month']);
225     if (!empty($data['direction'])) {
226       switch ($data['direction']) {
227       case 'prev':
228         if ($month > 1) $month--;
229         else {$year--; $month = 12;}
230         break;
231       case 'next':
232         if ($month < 12) $month++;
233         else {$year++; $month = 1;}
234         break;
235       }
236     }
237
238     $monthStr = sprintf('%04d-%02d', $year, $month);
239     $monthText = utf8_encode($monthname[intval($month)] . ' ' . $year);
240     $numdays = cal_days_in_month(CAL_GREGORIAN, $month, $year);
241
242     list($areaDates, $regDates) = $this->getMonthData($year, $month);
243
244     $out = '<div class="month">';
245
246     $out .= <<<EOT
247 <table width="100%" cellspacing="0" border="collapse">
248 <thead>
249 <tr><td colspan="8" class="title">{$monthText}</td></tr>
250 <tr>
251       <td width="2%">&nbsp;</td>
252       <td width="14%">Montag</td>
253       <td width="14%">Dienstag</td>
254       <td width="14%">Mittwoch</td>
255       <td width="14%">Donnerstag</td>
256       <td width="14%">Freitag</td>
257       <td width="14%">Samstag</td>
258       <td width="14%">Sonntag</td>
259 </tr>
260 </thead>
261 <tbody>
262 EOT;
263
264     $timestamp = mktime (4, 0, 0, $month, 1, $year);
265     if (date('N', $timestamp) != 1) {
266       $out .= '<tr>';
267       $out .= sprintf('<td width="2%%">%d</td>', date('W', $timestamp));
268       for ($i=1; $i < date('N', $timestamp); $i++)
269         $out .= '<td width="14%" class="empty">&nbsp;</td>';
270     }
271
272     $today = date('Y-m-d');
273     for ($day=1; $day <= $numdays; $day++) {
274       $timestamp = mktime (4, 0, 0, $month, $day, $year);
275       $date = sprintf('%04d-%02d-%02d', $year, $month, $day);
276       if (date('N', $timestamp) == 1)
277         $out .= sprintf('<tr><td width="2%%">%d</td>', date('W', $timestamp));
278
279       $items = array();
280
281       if (array_key_exists($date, $areaDates))
282         foreach ($areaDates[$date] as $item)
283           $items[] = $item->toSpan();
284
285       if (array_key_exists($date, $regDates))
286         foreach ($regDates[$date] as $item)
287           $items[] = $item->toSpan();
288
289       $out .= sprintf('<td width="14%%"><div class="day">%d</day><div>%s</div></td>',
290                       date('d', $timestamp),
291                       count($items) ? implode('<br />', $items) : '&nbsp;');
292
293       if (date('N', $timestamp) == 7)
294         $out .= '</tr>';
295     }
296
297     if (date('N', $timestamp) != 7) {
298       for ($i=date('N', $timestamp); $i < 7; $i++)
299         $out .= '<td width="14%" class="empty">&nbsp;</td>';
300       $out .= '</tr>';
301     }
302
303     $out .= '</tbody></table>';
304
305     $out .= '</div>';
306
307     return array('values' => array('thismonth' => $monthStr),
308                  'html' => array('termine' => $out));
309   }
310
311 }