exporting implemented. TODO: add timezone to ics

This commit is contained in:
Christoph Haas 2016-06-21 11:15:18 +02:00
parent 02b235a1ed
commit 3f3f624b66
2 changed files with 217 additions and 1 deletions

View File

@ -30,6 +30,12 @@ class CalendarModule extends Module
private $DEBUG = true; // enable error_log debugging private $DEBUG = true; // enable error_log debugging
private $busystates = null;
private $labels = null;
private $attendeetype = null;
/** /**
* @constructor * @constructor
* @param $id * @param $id
@ -38,6 +44,38 @@ class CalendarModule extends Module
public function __construct($id, $data) public function __construct($id, $data)
{ {
parent::Module($id, $data); parent::Module($id, $data);
// init default timezone
date_default_timezone_set(PLUGIN_CALENDARIMPORTER_DEFAULT_TIMEZONE);
// init mappings
$this->busystates = array(
"FREE",
"TENTATIVE",
"BUSY",
"OOF"
);
$this->labels = array(
"NONE",
"IMPORTANT",
"WORK",
"PERSONAL",
"HOLIDAY",
"REQUIRED",
"TRAVEL REQUIRED",
"PREPARATION REQUIERED",
"BIRTHDAY",
"SPECIAL DATE",
"PHONE INTERVIEW"
);
$this->attendeetype = array(
"NON-PARTICIPANT", // needed as zarafa starts counting at 1
"REQ-PARTICIPANT",
"OPT-PARTICIPANT",
"NON-PARTICIPANT"
);
} }
/** /**
@ -114,6 +152,63 @@ class CalendarModule extends Module
return $pass; return $pass;
} }
/**
* Get a property from the array.
* @param $props
* @param $propname
* @return string
*/
private function getProp($props, $propname)
{
if (isset($props["props"][$propname])) {
return $props["props"][$propname];
}
return "";
}
private function getDurationStringFromMintues($minutes, $pos = false) {
$pos = $pos === true ? "+" : "-";
$str = $pos . "P";
// variables for holding values
$mins = intval($minutes);
$hours = 0;
$days = 0;
$weeks = 0;
// calculations
if ( $mins >= 60 ) {
$hours = (int)($mins / 60);
$mins = $mins % 60;
}
if ( $hours >= 24 ) {
$days = (int)($hours / 24);
$hours = $hours % 60;
}
if ( $days >= 7 ) {
$weeks = (int)($days / 7);
$days = $days % 7;
}
// format result
if ( $weeks ) {
$str .= "{$weeks}W";
}
if ( $days ) {
$str .= "{$days}D";
}
if ( $hours ) {
$str .= "{$hours}H";
}
if ( $mins ) {
$str .= "{$mins}M";
}
return $str;
}
/** /**
* The main export function, creates the ics file for download * The main export function, creates the ics file for download
* @param $actionType * @param $actionType
@ -121,7 +216,127 @@ class CalendarModule extends Module
*/ */
private function exportCalendar($actionType, $actionData) private function exportCalendar($actionType, $actionData)
{ {
// TODO: implement // Get store id
$storeid = false;
if (isset($actionData["storeid"])) {
$storeid = $actionData["storeid"];
}
// Get records
$records = array();
if (isset($actionData["records"])) {
$records = $actionData["records"];
}
// Get folders
$folder = false;
if (isset($actionData["folder"])) {
$folder = $actionData["folder"];
}
$response = array();
$error = false;
$error_msg = "";
// write csv
$token = $this->randomstring(16);
$file = PLUGIN_CALENDARIMPORTER_TMP_UPLOAD . "ics_" . $token . ".ics";
file_put_contents($file, "");
$store = $GLOBALS["mapisession"]->openMessageStore(hex2bin($storeid));
if ($store) {
// load folder first
if ($folder !== false) {
$mapifolder = mapi_msgstore_openentry($store, hex2bin($folder));
$table = mapi_folder_getcontentstable($mapifolder);
$list = mapi_table_queryallrows($table, array(PR_ENTRYID));
foreach ($list as $item) {
$records[] = bin2hex($item[PR_ENTRYID]);
}
}
$vcalendar = new VObject\Component\VCalendar();
for ($index = 0, $count = count($records); $index < $count; $index++) {
$message = mapi_msgstore_openentry($store, hex2bin($records[$index]));
// get message properties.
$properties = $GLOBALS['properties']->getAppointmentProperties();
$plaintext = true;
$messageProps = $GLOBALS['operations']->getMessageProps($store, $message, $properties, $plaintext);
$vevent = $vcalendar->add('VEVENT', [
'SUMMARY' => $this->getProp($messageProps, "subject"),
'DTSTART' => date_timestamp_set(new DateTime(), $this->getProp($messageProps, "startdate")),
'DTEND' => date_timestamp_set(new DateTime(), $this->getProp($messageProps, "duedate")),
'CREATED' => date_timestamp_set(new DateTime(), $this->getProp($messageProps, "creation_time")),
'LAST-MODIFIED' => date_timestamp_set(new DateTime(), $this->getProp($messageProps, "last_modification_time")),
'PRIORITY' => $this->getProp($messageProps, "importance"),
'X-MICROSOFT-CDO-INTENDEDSTATUS' => $this->busystates[intval($this->getProp($messageProps, "busystatus"))], // both seem to be valid...
'X-MICROSOFT-CDO-BUSYSTATUS' => $this->busystates[intval($this->getProp($messageProps, "busystatus"))], // both seem to be valid...
'X-ZARAFA-LABEL' => $this->labels[intval($this->getProp($messageProps, "label"))],
'CLASS' => $this->getProp($messageProps, "private") ? "PRIVATE" : "PUBLIC",
'COMMENT' => "eid:" . $records[$index]
]);
// Add organizer
$vevent->add('ORGANIZER','mailto:' . $this->getProp($messageProps, "sender_email_address"));
$vevent->ORGANIZER['CN'] = $this->getProp($messageProps, "sender_name");
// Add Attendees
if(isset($messageProps["recipients"]) && count($messageProps["recipients"]["item"]) > 0) {
foreach($messageProps["recipients"]["item"] as $attendee) {
$att = $vevent->add('ATTENDEE', "mailto:" . $this->getProp($attendee, "email_address"));
$att["CN"] = $this->getProp($attendee, "display_name");
$att["ROLE"] = $this->attendeetype[intval($this->getProp($attendee, "recipient_type"))];
}
}
// Add alarms
if(!empty($this->getProp($messageProps, "reminder")) && $this->getProp($messageProps, "reminder") == 1) {
$valarm = $vevent->add('VALARM', [
'ACTION' => 'DISPLAY',
'DESCRIPTION' => $this->getProp($messageProps, "subject") // reuse the event summary
]);
// Add trigger
$durationValue = $this->getDurationStringFromMintues($this->getProp($messageProps, "reminder_minutes"), false);
$valarm->add('TRIGGER', $durationValue); // default trigger type is duration (see 4.8.6.3)
/*
$valarm->add('TRIGGER', date_timestamp_set(new DateTime(), $this->getProp($messageProps, "reminder_time"))); // trigger type "DATE-TIME"
$valarm->TRIGGER['VALUE'] = 'DATE-TIME';
*/
}
// Add location
if(!empty($this->getProp($messageProps, "location"))) {
$vevent->add('LOCATION',$this->getProp($messageProps, "location"));
}
// Add description
$body = $this->getProp($messageProps, "isHTML") ? $this->getProp($messageProps, "html_body") : $this->getProp($messageProps, "body");
if(!empty($body)) {
$vevent->add('DESCRIPTION',$body);
}
}
// write combined ics file
file_put_contents($file, file_get_contents($file) . $vcalendar->serialize());
}
if (count($records) > 0) {
$response['status'] = true;
$response['download_token'] = $token;
$response['filename'] = count($records) . "events.ics";
} else {
$response['status'] = false;
$response['message'] = "No events found. Export skipped!";
}
$this->addActionData($actionType, $response);
$GLOBALS["bus"]->addData($this->getResponseData());
} }
/** /**

View File

@ -45,6 +45,7 @@ class Plugincalendarimporter extends Plugin
function init() function init()
{ {
$this->registerHook('server.core.settings.init.before'); $this->registerHook('server.core.settings.init.before');
$this->registerHook('server.index.load.custom');
} }
/** /**