1: <?php
2: 3: 4: 5: 6: 7: 8:
9: class Kronolith_View_Week
10: {
11: public $parsed = false;
12: public $days = array();
13: public $week = null;
14: public $year = null;
15: public $startDay = null;
16: public $endDay = null;
17: public $startDate = null;
18: protected $_controller = 'week.php';
19: public $sidebyside = false;
20: public $_currentCalendars = array();
21:
22: 23: 24: 25: 26:
27: public $_slotsPerHour = 2;
28:
29: 30: 31: 32: 33: 34:
35: public $_slotsPerDay;
36:
37: public function __construct(Horde_Date $date)
38: {
39: $week = $date->weekOfYear();
40: $year = $date->year;
41: if (!$GLOBALS['prefs']->getValue('week_start_monday') &&
42: $date->dayOfWeek() == Horde_Date::DATE_SUNDAY) {
43: ++$week;
44: }
45: if ($week > 51 && $date->month == 1) {
46: --$year;
47: } elseif ($week == 1 && $date->month == 12) {
48: ++$year;
49: }
50:
51: $this->year = $year;
52: $this->week = $week;
53: $day = Horde_Date_Utils::firstDayOfWeek($week, $year);
54:
55: if (!isset($this->startDay)) {
56: if ($GLOBALS['prefs']->getValue('week_start_monday')) {
57: $this->startDay = Horde_Date::DATE_MONDAY;
58: $this->endDay = Horde_Date::DATE_SUNDAY + 7;
59: } else {
60: $day->mday--;
61: $this->startDay = Horde_Date::DATE_SUNDAY;
62: $this->endDay = Horde_Date::DATE_SATURDAY;
63: }
64: }
65:
66: $this->startDate = new Horde_Date($day);
67: for ($i = $this->startDay; $i <= $this->endDay; ++$i) {
68: $this->days[$i] = new Kronolith_View_Day($day, array());
69: $day->mday++;
70: }
71: $endDate = new Horde_Date($day);
72: try {
73: $allevents = Kronolith::listEvents($this->startDate, $endDate);
74: } catch (Exception $e) {
75: $GLOBALS['notification']->push($e, 'horde.error');
76: $allevents = array();
77: }
78: for ($i = $this->startDay; $i <= $this->endDay; ++$i) {
79: $date_stamp = $this->days[$i]->dateString();
80: $this->days[$i]->events = isset($allevents[$date_stamp])
81: ? $allevents[$date_stamp]
82: : array();
83: }
84: $this->sidebyside = $this->days[$this->startDay]->sidebyside;
85: $this->_currentCalendars = $this->days[$this->startDay]->currentCalendars;
86: $this->slotsPerHour = $this->days[$this->startDay]->slotsPerHour;
87: $this->slotsPerDay = $this->days[$this->startDay]->slotsPerDay;
88: $this->slotLength = $this->days[$this->startDay]->slotLength;
89: }
90:
91: public function html()
92: {
93: global $prefs;
94:
95: $more_timeslots = $prefs->getValue('time_between_days');
96: $include_all_events = !$prefs->getValue('show_shared_side_by_side');
97: $showLocation = Kronolith::viewShowLocation();
98: $showTime = Kronolith::viewShowTime();
99:
100: if (!$this->parsed) {
101: $this->parse();
102: }
103:
104: $slots = $this->days[$this->startDay]->slots;
105: $cid = 0;
106: require KRONOLITH_TEMPLATES . '/week/head.inc';
107: if ($this->sidebyside) {
108: require KRONOLITH_TEMPLATES . '/week/head_side_by_side.inc';
109: }
110: echo '</thead><tbody>';
111:
112: $event_count = 0;
113: for ($j = $this->startDay; $j <= $this->endDay; ++$j) {
114: foreach (array_keys($this->_currentCalendars) as $cid) {
115: $event_count = max($event_count, count($this->days[$j]->all_day_events[$cid]));
116: reset($this->days[$j]->all_day_events[$cid]);
117: }
118: }
119:
120: if ($more_timeslots) {
121: $newEventUrl = null;
122: } else {
123: $newEventUrl = _("All day");
124: }
125:
126: $row = '';
127: for ($j = $this->startDay; $j <= $this->endDay; ++$j) {
128: $row .= '<td class="hour rightAlign daySpacer">' . ($more_timeslots ? _("All day") : ' ') . '</td>' .
129: '<td colspan="' . $this->days[$j]->totalspan . '" valign="top"><table width="100%" cellspacing="0">';
130: if ($this->days[$j]->all_day_maxrowspan > 0) {
131: for ($k = 0; $k < $this->days[$j]->all_day_maxrowspan; ++$k) {
132: $row .= '<tr>';
133: foreach (array_keys($this->days[$j]->currentCalendars) as $cid) {
134: if (count($this->days[$j]->all_day_events[$cid]) === $k) {
135: $row .= '<td rowspan="' . ($this->days[$j]->all_day_maxrowspan - $k) . '" width="'. round(99 / count($this->days[$j]->currentCalendars)) . '%"> </td>';
136: } elseif (count($this->days[$j]->all_day_events[$cid]) > $k) {
137: $event = $this->days[$j]->all_day_events[$cid][$k];
138: $row .= '<td class="week-eventbox"'
139: . $event->getCSSColors()
140: . 'width="' . round(99 / count($this->days[$j]->currentCalendars)) . '%" '
141: . 'valign="top">'
142: . $event->getLink($this->days[$j], true, $this->link(0, true));
143: if (!$event->isPrivate() && $showLocation) {
144: $row .= '<div class="event-location">' . htmlspecialchars($event->getLocation()) . '</div>';
145: }
146: $row .= '</td>';
147: }
148: }
149: $row .= '</tr>';
150: }
151: } else {
152: $row .= '<tr><td colspan="' . count($this->_currentCalendars) . '"> </td></tr>';
153: }
154: $row .= '</table></td>';
155: }
156:
157: $rowspan = '';
158: $first_row = true;
159: require KRONOLITH_TEMPLATES . '/day/all_day.inc';
160:
161: $day_hour_force = $prefs->getValue('day_hour_force');
162: $day_hour_start = $prefs->getValue('day_hour_start') / 2 * $this->slotsPerHour;
163: $day_hour_end = $prefs->getValue('day_hour_end') / 2 * $this->slotsPerHour;
164: $rows = array();
165: $covered = array();
166:
167: for ($i = 0; $i < $this->slotsPerDay; ++$i) {
168: if ($i >= $day_hour_end && $i > $this->last) {
169: break;
170: }
171: if ($i < $this->first && $i < $day_hour_start) {
172: continue;
173: }
174:
175: if (($m = $i % $this->slotsPerHour) != 0) {
176: $time = ':' . $m * $this->slotLength;
177: $hourclass = 'halfhour';
178: } else {
179: $time = Kronolith_View_Day::prefHourFormat($slots[$i]['hour']);
180: $hourclass = 'hour';
181: }
182:
183: $row = '';
184: for ($j = $this->startDay; $j <= $this->endDay; ++$j) {
185:
186: if ($more_timeslots) {
187: $row .= '<td align="right" class="' . $hourclass . ' daySpacer">' . $time . '</td>';
188: } else {
189: $row .= '<td class="daySpacer"> </td>';
190: }
191:
192: if (!count($this->_currentCalendars)) {
193: $row .= '<td> </td>';
194: }
195:
196: foreach (array_keys($this->_currentCalendars) as $cid) {
197:
198:
199: $hspan = 0;
200:
201: $current_indent = 0;
202:
203:
204:
205: for (; isset($covered[$j][$i][$current_indent]); ++$current_indent);
206:
207: foreach ($this->days[$j]->event_matrix[$cid][$i] as $key) {
208: $event = &$this->days[$j]->events[$key];
209: if ($include_all_events || $event->calendar == $cid) {
210:
211:
212:
213:
214:
215: $span = $this->days[$j]->span[$cid] / $event->overlap;
216:
217:
218:
219: if (!isset($event->indent)) {
220: $event->indent = $current_indent;
221: }
222:
223:
224:
225: if (!isset($event->span)) {
226:
227:
228:
229:
230:
231:
232:
233: if (!isset($covered[$j][$i][$event->indent])) {
234: $collision = false;
235: $available = 0;
236: for ($y = $event->indent; $y < ($span + $event->indent); ++$y) {
237: if (isset($covered[$j][$i][$y])) {
238: $collision = true;
239: break;
240: }
241: $available++;
242: }
243:
244: if ($collision) {
245: $span = $available;
246: }
247: }
248:
249:
250:
251:
252:
253:
254:
255: $event->span = ceil($span);
256: }
257:
258: $hspan += $event->span;
259: $current_indent += $event->span;
260:
261: $start = new Horde_Date(array(
262: 'hour' => floor($i / $this->slotsPerHour),
263: 'min' => ($i % $this->slotsPerHour) * $this->slotLength,
264: 'month' => $this->days[$j]->month,
265: 'mday' => $this->days[$j]->mday,
266: 'year' => $this->days[$j]->year));
267: $slot_end = new Horde_Date($start);
268: $slot_end->min += $this->slotLength;
269: if (((!$day_hour_force || $i >= $day_hour_start) &&
270: $event->start->compareDateTime($start) >= 0 &&
271: $event->start->compareDateTime($slot_end) < 0 ||
272: $start->compareDateTime($this->days[$j]) == 0) ||
273: ($day_hour_force &&
274: $i == $day_hour_start)) {
275:
276:
277:
278: for ($x = $i; $x < ($i + $event->rowspan); ++$x) {
279: for ($y = $event->indent; $y < $current_indent; ++$y) {
280: $covered[$j][$x][$y] = true;
281: }
282: }
283:
284: $row .= '<td class="week-eventbox"'
285: . $event->getCSSColors()
286: . 'valign="top" '
287: . 'width="' . floor(((90 / count($this->days)) / count($this->_currentCalendars)) * ($span / $this->days[$j]->span[$cid])) . '%" '
288: . 'colspan="' . $event->span . '" rowspan="' . $event->rowspan . '">'
289: . $event->getLink($this->days[$j], true, $this->link(0, true));
290: if ($showTime) {
291: $row .= '<div class="event-time">' . htmlspecialchars($event->getTimeRange()) . '</div>';
292: }
293: if (!$event->isPrivate() && $showLocation) {
294: $row .= '<div class="event-location">' . htmlspecialchars($event->getLocation()) . '</div>';
295: }
296: $row .= '</td>';
297: }
298: }
299: }
300:
301: $diff = $this->days[$j]->span[$cid] - $hspan;
302: if ($diff > 0) {
303: $row .= str_repeat('<td> </td>', $diff);
304: }
305: }
306: }
307:
308: $rows[] = array('row' => $row, 'slot' => '<span class="' . $hourclass . '">' . $time . '</span>');
309: }
310:
311: $template = $GLOBALS['injector']->createInstance('Horde_Template');
312: $template->set('row_height', round(20 / $this->slotsPerHour));
313: $template->set('rows', $rows);
314: $template->set('show_slots', !$more_timeslots, true);
315: echo $template->fetch(KRONOLITH_TEMPLATES . '/day/rows.html')
316: . '</tbody></table>';
317: }
318:
319: 320: 321: 322: 323:
324: public function parse()
325: {
326: for ($i = $this->startDay; $i <= $this->endDay; ++$i) {
327: $this->days[$i]->parse();
328: }
329:
330: $this->totalspan = 0;
331: $this->span = array();
332: for ($i = $this->startDay; $i <= $this->endDay; ++$i) {
333: $this->totalspan += $this->days[$i]->totalspan;
334: foreach (array_keys($this->_currentCalendars) as $cid) {
335: if (isset($this->span[$cid])) {
336: $this->span[$cid] += $this->days[$i]->span[$cid];
337: } else {
338: $this->span[$cid] = $this->days[$i]->span[$cid];
339: }
340: }
341: }
342:
343: $this->last = 0;
344: $this->first = $this->slotsPerDay;
345: for ($i = $this->startDay; $i <= $this->endDay; ++$i) {
346: if ($this->days[$i]->last > $this->last) {
347: $this->last = $this->days[$i]->last;
348: }
349: if ($this->days[$i]->first < $this->first) {
350: $this->first = $this->days[$i]->first;
351: }
352: }
353: }
354:
355: public function getWeek($offset = 0)
356: {
357: $week = new Horde_Date($this->startDate);
358: $week->mday += $offset * 7;
359: return $week;
360: }
361:
362: public function link($offset = 0, $full = false)
363: {
364: $week = $this->getWeek($offset);
365: return Horde::url($this->_controller, $full)
366: ->add('date', $week->dateString());
367: }
368:
369: public function getName()
370: {
371: return 'Week';
372: }
373:
374: }
375: