tiki-calendar_export_ical.php 7.68 KB
Newer Older
1
<?php
changi67's avatar
changi67 committed
2 3 4
/**
 * @package tikiwiki
 */
5
// (c) Copyright 2002-2016 by authors of the Tiki Wiki CMS Groupware Project
6
//
changi67's avatar
changi67 committed
7 8 9 10
// All Rights Reserved. See copyright.txt for details and a complete list of authors.
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
// $Id$

11 12
require_once('tiki-setup.php');

13
$access->check_feature('feature_calendar');
14
$access->check_permission('tiki_p_view_events');
15 16 17

// Initialization
TikiInit::appendIncludePath("lib/ical/");
rjsmelo's avatar
rjsmelo committed
18
include_once('lib/ical/iCal.php');
19 20

// list calendars //
lphuberdeau's avatar
lphuberdeau committed
21
$calendarlib = TikiLib::lib('calendar');
22

23
// ###trebly:B10111:[FIX-ADD-ENH]->  there are several meaning for the same var $calendarViewMode
rjsmelo's avatar
rjsmelo committed
24
if (! isset($calendarViewMode)) {
25 26
// ###trebly:B10111:[FIX-ADD-ENH]-> $calendarViewMode become an array, several bugs comes from confusion of global values and parameters by ref
// for calendars : (main-)calendar, action_calendar, mod_calendar, mod_action_calendar the changes of values by url request is terrible
27
// for the moment 01/11/2011:11:55 just one value is used with index 'default', but initialisation is done.
28 29
// The init is actually into two places, tiki-calendar_setup.php and tiki-calendar_export.php will be grouped for clean
// $prefs would be added when need, $_SESSION, $PARAMS too this now generates not any change in the behavior.
rjsmelo's avatar
rjsmelo committed
30 31 32 33 34 35 36 37 38
	$calendarViewMode = [casedefault => 'month',calgen => 'month',calaction => 'month',modcalgen => 'month',modcalaction => 'month',trackercal => 'month'];

	if (! empty($_REQUEST['viewmode'])) {
		$calendarViewMode['casedefault'] = $_REQUEST['viewmode'];
	} elseif (! empty($_SESSION['CalendarViewMode'])) {
		$calendarViewMode['casedefault'] = $_SESSION['CalendarViewMode'];
	} else {
		$calendarViewMode['casedefault'] = $prefs['calendar_view_mode'];
	}
39 40
}

41 42 43
# If specified, limit the export to the maximum number of records (events)
# indicated in the request; otherwise, the limit is from the global preferences.
if (isset($_REQUEST['maxRecords'])) {
rjsmelo's avatar
rjsmelo committed
44
		$maxRecords = $_REQUEST['maxRecords'];
45 46
}

rjsmelo's avatar
rjsmelo committed
47
if (isset($_SESSION['CalendarFocusDate'])) {
48 49
	$startTime = $_SESSION['CalendarFocusDate'];
} else {
50
// by default, export will start from yesterday's events.
51 52 53 54
	$startDate = new TikiDate();
	$startDate->addDays(-1);
	$startTime = $startDate->getTime();
}
55

56
if (isset($_REQUEST['start_date_Month'])) {
57
	$startTime = TikiLib::make_time(0, 0, 0, $_REQUEST['start_date_Month'], $_REQUEST['start_date_Day'], $_REQUEST['start_date_Year']);
58
} elseif (isset($_REQUEST["tstart"])) {
59
	$startTime = $_REQUEST["tstart"];
60
}
61 62 63

$endDate = new TikiDate();
$endDate->setDate($startTime);
64
if ($calendarViewMode['casedefault'] == 'month') {
rjsmelo's avatar
rjsmelo committed
65
	 $stopTime = $endDate->addMonths(1);
66
} elseif ($calendarViewMode['casedefault'] == 'quarter') {
rjsmelo's avatar
rjsmelo committed
67
	$stopTime = $endDate->addMonths(3);
68
} elseif ($calendarViewMode['casedefault'] == 'semester') {
rjsmelo's avatar
rjsmelo committed
69
	$stopTime = $endDate->addMonths(6);
70
} elseif ($calendarViewMode['casedefault'] == 'year') {
rjsmelo's avatar
rjsmelo committed
71
	$stopTime = $endDate->addMonths(12);
72
} else {
rjsmelo's avatar
rjsmelo committed
73
	$stopTime = $endDate->addMonths(1);
74
}
75 76
$stopTime = $endDate->getTime();

77
if (isset($_REQUEST['stop_date_Month'])) {
78
	$stopTime = TikiLib::make_time(0, 0, 0, $_REQUEST['stop_date_Month'], $_REQUEST['stop_date_Day'], $_REQUEST['stop_date_Year']);
79
} elseif (isset($_REQUEST["tstop"])) {
80
	$stopTime = $_REQUEST["tstop"];
81
}
82

rjsmelo's avatar
rjsmelo committed
83
$calendarIds = [];
84 85
if (isset($_REQUEST['calendarIds'])) {
	$calendarIds = $_REQUEST['calendarIds'];
rjsmelo's avatar
rjsmelo committed
86 87 88
	foreach ($calendarIds as $anId) {
		$smarty->assign('individual_' . $anId, $userlib->object_has_one_permission($anId, 'calendar'));
	}
89
} else {
rjsmelo's avatar
rjsmelo committed
90
	if (! isset($_REQUEST["calendarId"])) {
91 92
		$_REQUEST["calendarId"] = 0;
	} else {
rjsmelo's avatar
rjsmelo committed
93
		 $smarty->assign('individual_' . $_REQUEST["calendarId"], $userlib->object_has_one_permission($_REQUEST["calendarId"], 'calendar'));
94
	}
95
}
rjsmelo's avatar
rjsmelo committed
96
$sort_mode = "name";
97

rjsmelo's avatar
rjsmelo committed
98
$find = "";
99 100 101 102 103
$calendars = $calendarlib->list_calendars(0, -1, $sort_mode, $find);

foreach (array_keys($calendars["data"]) as $i) {
	$calendars["data"][$i]["individual"] = $userlib->object_has_one_permission($i, 'calendar');
}
104
$smarty->assign('calendars', $calendars["data"]);
105

106
// export calendar //
rjsmelo's avatar
rjsmelo committed
107
if (((is_array($calendarIds) && (count($calendarIds) > 0)) or isset($_REQUEST["calendarItem"]) ) && $_REQUEST["export"] == 'y') {
108
	// get calendar events
rjsmelo's avatar
rjsmelo committed
109
	if (! isset($_REQUEST["calendarItem"])) {
110
		$events = $calendarlib->list_raw_items($calendarIds, $user, $startTime, $stopTime, -1, $maxRecords, $sort_mode = 'start_asc', $find = '');
111
	} else {
112
		$events[] = $calendarlib->get_item($_REQUEST["calendarItem"]);
113
	}
114

rjsmelo's avatar
rjsmelo committed
115
	if (isset($_REQUEST['csv'])) {
116 117 118 119
		header('Content-type: text/csv');
		header("Content-Disposition: inline; filename=tiki-calendar.csv");
		$first = true;
		$description = '';
120
		foreach ($events as $event) {
121
			$line = '';
122
			foreach ($event as $name => $field) {
rjsmelo's avatar
rjsmelo committed
123 124
				if ($first === true) {
					$description .= '"' . $name . '";';
125
				}
rjsmelo's avatar
rjsmelo committed
126 127
				if (is_array($field)) {
					$line .= '"' . str_replace(["\n","\r",'"'], ['\\n','','""'], join(',', $field)) . '";';
128
				} else {
rjsmelo's avatar
rjsmelo committed
129
					$line .= '"' . str_replace(["\n","\r",'"'], ['\\n','','""'], $field) . '";';
130 131
				}
			}
rjsmelo's avatar
rjsmelo committed
132 133
			if ($first === true) {
				echo (trim($description, ';')) . "\n";
134 135
				$first = false;
			}
rjsmelo's avatar
rjsmelo committed
136
			echo trim($line, ';') . "\n";
137
		}
138
	} else {
139 140 141 142 143
		// create ical array//
		$iCal = new File_iCal();

		$cal = $iCal->getSkeletonCalendar();
		foreach ($events as $event) {
rjsmelo's avatar
rjsmelo committed
144 145 146 147 148
			$ea = [];
			$ea['Summary'] = $event['name'];
			$ea['dateStart'] = $event['start'];
			$ea['dateEnd'] = $event['end'];
			$ea['Description'] = preg_replace(
changi67's avatar
changi67 committed
149 150 151
				'/\n/',
				"\\n",
				strip_tags(
152 153
					TikiLib::lib('parser')->parse_data(
						$event['description'],
rjsmelo's avatar
rjsmelo committed
154
						['is_html' => $prefs['calendar_description_is_html'] === 'y']
155 156 157
					)
				)
			);
158
			if ($event['participants']) {
rjsmelo's avatar
rjsmelo committed
159
				$ea['Attendees'] = $event['participants'];
160
			}
rjsmelo's avatar
rjsmelo committed
161
			$ea['LastModified'] = $event['lastModif'];
162 163 164 165 166 167 168 169 170 171 172

			// re: Second character of duration value must be a 'P' ??
			// jb for tiki 11 - feb 2013
			// spec is at: https://tools.ietf.org/html/rfc5545#section-3.3.6, so i tried:
			//	$durationSeconds = $event['end'] - $event['start'];
			//	$duration = $durationSeconds > 0 ? '+' : '-';
			//	$duration .= 'P' . $durationSeconds . 'S';
			// however, when formatted seemingly correctly you then get an error saying it's not in integer! :(
			// so just removing duration for now as it's implied by the start and end anyway - TODO better
			// $ea['Duration']=($duration);

rjsmelo's avatar
rjsmelo committed
173 174 175
			$ea['Contact'] = [$event['user']];
			if (! empty($event['organizers'])) {
				$ea['organizer'] = [$event['organizers']];
176
			}
rjsmelo's avatar
rjsmelo committed
177 178
			if (! empty($event['url'])) {
				$ea['URL'] = $event['url'];
179
			}
rjsmelo's avatar
rjsmelo committed
180
			$ea['DateStamp'] = $event['created'];
181
			//$ea['RequestStatus']=$event['status'];
rjsmelo's avatar
rjsmelo committed
182
			$ea['UID'] = 'tiki-' . $event['calendarId'] . '-' . $event['calitemId'];
183
			$c = $iCal->factory('Event', $ea);
184 185 186 187 188
			$cal->addEvent($c);
		}
		$iCal->addCalendar($cal);
		$iCal->sendHeader("calendar");
		$calendar_str = $iCal->__toString();
rjsmelo's avatar
rjsmelo committed
189
		header("Content-Length: " . strlen($calendar_str));
190 191 192 193
		header("Expires: 0");
		// These two lines fix pb with IE and HTTPS
		header("Cache-Control: private");
		header("Pragma: dummy=bogus");
194
		// Outlook needs iso8859 encoding
195 196 197 198
		header("Content-Type:text/calendar; method=REQUEST; charset=iso-8859-15");
		header("Content-Transfer-Encoding:quoted-printable");
		$re_encode = stripos($_SERVER['HTTP_USER_AGENT'], 'windows');	// only re-encode to ISO-8859-15 if client on Windows
		if (function_exists('recode') && $re_encode !== false) {
199
			print(recode('utf-8..iso8859-15', $calendar_str));
200 201 202 203 204
		} elseif (function_exists('iconv') && $re_encode !== false) {
			print(iconv("UTF-8", "ISO-8859-15", $calendar_str));
		} else {
			print($calendar_str);	// UTF-8 is good for other platforms
		}
205
	}
206 207 208 209 210 211 212
	die;
}


$smarty->assign('iCal', $iCal);

// Display the template
213
$smarty->assign('mid', 'tiki-calendar_export_ical.tpl');
214
$smarty->display("tiki.tpl");