Heavily refactored, including multiple calendars per user and recurring events. Not in an installable state yet, though

This commit is contained in:
Tobias Hößl 2012-07-08 17:12:58 +00:00
parent 4a5e30ec84
commit fefee23e90
78 changed files with 8026 additions and 1205 deletions

View file

@ -1,6 +1,11 @@
<?php
define("DAV_ACL_READ", "{DAV:}read");
define("DAV_ACL_WRITE", "{DAV:}write");
define("DAV_DISPLAYNAME", "{DAV:}displayname");
class vcard_source_data_email
{
public $email, $type;
@ -83,7 +88,7 @@ class vcard_source_data
/** @var array|vcard_source_data_email[] $email */
public $emails;
/** @var array|vcard_source_data_addresses[] $addresses */
/** @var array|vcard_source_data_address[] $addresses */
public $addresses;
/** @var vcard_source_data_photo */
@ -136,41 +141,6 @@ function vcard_source_compile($vcardsource)
}
/**
* @param array $start
* @param array $end
* @param bool $allday
* @return vevent
*/
function dav_create_vevent($start, $end, $allday)
{
if ($end["year"] < $start["year"] ||
($end["year"] == $start["year"] && $end["month"] < $start["month"]) ||
($end["year"] == $start["year"] && $end["month"] == $start["month"] && $end["day"] < $start["day"]) ||
($end["year"] == $start["year"] && $end["month"] == $start["month"] && $end["day"] == $start["day"] && $end["hour"] < $start["hour"]) ||
($end["year"] == $start["year"] && $end["month"] == $start["month"] && $end["day"] == $start["day"] && $end["hour"] == $start["hour"] && $end["minute"] < $start["minute"]) ||
($end["year"] == $start["year"] && $end["month"] == $start["month"] && $end["day"] == $start["day"] && $end["hour"] == $start["hour"] && $end["minute"] == $start["minute"] && $end["second"] < $start["second"])
) {
$end = $start;
} // DTEND muss <= DTSTART
$vevent = new vevent();
if ($allday) {
$vevent->setDtstart($start["year"], $start["month"], $start["day"], FALSE, FALSE, FALSE, FALSE, array("VALUE"=> "DATE"));
$end = IntVal(mktime(0, 0, 0, $end["month"], $end["day"], $end["year"]) + 3600 * 24);
// If a DST change occurs on the current day
$end += IntVal(date("Z", ($end - 3600 * 24)) - date("Z", $end));
$vevent->setDtend(date("Y", $end), date("m", $end), date("d", $end), FALSE, FALSE, FALSE, FALSE, array("VALUE"=> "DATE"));
} else {
$vevent->setDtstart($start["year"], $start["month"], $start["day"], $start["hour"], $start["minute"], $start["second"], FALSE, array("VALUE"=> "DATE-TIME"));
$vevent->setDtend($end["year"], $end["month"], $end["day"], $end["hour"], $end["minute"], $end["second"], FALSE, array("VALUE"=> "DATE-TIME"));
}
return $vevent;
}
/**
* @param int $phpDate (UTC)
* @return string (Lokalzeit)
@ -216,457 +186,196 @@ function icalendar_sanitize_string($str = "")
$str = str_replace("\r\n", "\n", $str);
$str = str_replace("\n\r", "\n", $str);
$str = str_replace("\r", "\n", $str);
$str = str_replace("\n\n", "\n", $str);
$str = str_replace("\n\n", "\n", $str);
return $str;
}
/**
* @param DBClass_friendica_calendars $calendar
* @param DBClass_friendica_calendarobjects $calendarobject
* @return Sabre_CalDAV_AnimexxCalendarRootNode
*/
function renderCalDavEntry_data(&$calendar, &$calendarobject)
function dav_createRootCalendarNode()
{
$caldavBackend_std = Sabre_CalDAV_Backend_Private::getInstance();
$caldavBackend_community = Sabre_CalDAV_Backend_Friendica::getInstance();
return new Sabre_CalDAV_AnimexxCalendarRootNode(Sabre_DAVACL_PrincipalBackend_Std::getInstance(), array(
$caldavBackend_std,
$caldavBackend_community,
));
}
/**
* @return Sabre_CardDAV_AddressBookRootFriendica
*/
function dav_createRootContactsNode()
{
$carddavBackend_std = Sabre_CardDAV_Backend_Std::getInstance();
$carddavBackend_community = Sabre_CardDAV_Backend_FriendicaCommunity::getInstance();
return new Sabre_CardDAV_AddressBookRootFriendica(Sabre_DAVACL_PrincipalBackend_Std::getInstance(), array(
$carddavBackend_std,
$carddavBackend_community,
));
}
/**
* @param bool $force_authentication
* @param bool $needs_caldav
* @param bool $needs_carddav
* @return Sabre_DAV_Server
*/
function dav_create_server($force_authentication = false, $needs_caldav = true, $needs_carddav = true)
{
$arr = array(
new Sabre_DAV_SimpleCollection('principals', array(
new Sabre_CalDAV_Principal_Collection(Sabre_DAVACL_PrincipalBackend_Std::getInstance(), "principals/users"),
)),
);
if ($needs_caldav) $arr[] = dav_createRootCalendarNode();
if ($needs_carddav) $arr[] = dav_createRootContactsNode();
$tree = new Sabre_DAV_SimpleCollection('root', $arr);
// The object tree needs in turn to be passed to the server class
$server = new Sabre_DAV_Server($tree);
$server->setBaseUri(CALDAV_URL_PREFIX);
$authPlugin = new Sabre_DAV_Auth_Plugin(Sabre_DAV_Auth_Backend_Std::getInstance(), 'SabreDAV');
$server->addPlugin($authPlugin);
$aclPlugin = new Sabre_DAVACL_Plugin_Friendica();
$aclPlugin->defaultUsernamePath = "principals/users";
$server->addPlugin($aclPlugin);
if ($needs_caldav) {
$caldavPlugin = new Sabre_CalDAV_Plugin();
$server->addPlugin($caldavPlugin);
}
if ($needs_carddav) {
$carddavPlugin = new Sabre_CardDAV_Plugin();
$server->addPlugin($carddavPlugin);
}
if ($force_authentication) $server->broadcastEvent('beforeMethod', array("GET", "/")); // Make it authenticate
return $server;
}
/**
* @param Sabre_DAV_Server $server
* @param string $with_privilege
* @return array|Sabre_CalDAV_Calendar[]
*/
function dav_get_current_user_calendars(&$server, $with_privilege = "")
{
if ($with_privilege == "") $with_privilege = DAV_ACL_READ;
$a = get_app();
$calendar_path = "/calendars/" . strtolower($a->user["nickname"]) . "/";
/** @var Sabre_CalDAV_AnimexxUserCalendars $tree */
$tree = $server->tree->getNodeForPath($calendar_path);
/** @var array|Sabre_CalDAV_Calendar[] $calendars */
$children = $tree->getChildren();
$calendars = array();
/** @var Sabre_DAVACL_Plugin $aclplugin */
$aclplugin = $server->getPlugin("acl");
foreach ($children as $child) if (is_a($child, "Sabre_CalDAV_Calendar")) {
if ($with_privilege != "") {
$caluri = $calendar_path . $child->getName();
if ($aclplugin->checkPrivileges($caluri, $with_privilege, Sabre_DAVACL_Plugin::R_PARENT, false)) $calendars[] = $child;
} else {
$calendars[] = $child;
}
}
return $calendars;
}
/**
* @param Sabre_DAV_Server $server
* @param Sabre_CalDAV_Calendar $calendar
* @param string $calendarobject_uri
* @param string $with_privilege
* @return null|Sabre_VObject_Component_VEvent
*/
function dav_get_current_user_calendarobject(&$server, &$calendar, $calendarobject_uri, $with_privilege = "")
{
$obj = $calendar->getChild($calendarobject_uri);
if ($with_privilege == "") $with_privilege = DAV_ACL_READ;
$a = get_app();
$uri = "/calendars/" . strtolower($a->user["nickname"]) . "/" . $calendar->getName() . "/" . $calendarobject_uri;
/** @var Sabre_DAVACL_Plugin $aclplugin */
$aclplugin = $server->getPlugin("acl");
if (!$aclplugin->checkPrivileges($uri, $with_privilege, Sabre_DAVACL_Plugin::R_PARENT, false)) return null;
$data = $obj->get();
$vObject = Sabre_VObject_Reader::read($data);
return $vObject;
}
/**
* @param Sabre_DAV_Server $server
* @param int $id
* @param string $with_privilege
* @return null|Sabre_CalDAV_Calendar
*/
function dav_get_current_user_calendar_by_id(&$server, $id, $with_privilege = "")
{
$calendars = dav_get_current_user_calendars($server, $with_privilege);
$calendar = null;
foreach ($calendars as $cal) {
$prop = $cal->getProperties(array("id"));
if (isset($prop["id"]) && $prop["id"] == $id) $calendar = $cal;
}
return $calendar;
}
/**
* @param string $uid
* @return Sabre_VObject_Component_VEvent $vObject
*/
function dav_create_empty_vevent($uid = "")
{
$a = get_app();
if ($uid == "") $uid = uniqid();
return Sabre_VObject_Reader::read("BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Friendica//DAV-Plugin//EN\r\nBEGIN:VEVENT\r\nUID:" . $uid . "@" . $a->get_hostname() .
"\r\nDTSTAMP:" . date("Ymd") . "T" . date("His") . "Z\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n");
}
$v = new vcalendar();
$v->setConfig('unique_id', $a->get_hostname());
$v->parse($calendarobject->calendardata);
$v->sort();
$eventArray = $v->selectComponents(2009, 1, 1, date("Y") + 2, 12, 30);
$start_min = $end_max = "";
$allday = $summary = $vevent = $rrule = $color = $start = $end = null;
$location = $description = "";
foreach ($eventArray as $yearArray) {
foreach ($yearArray as $monthArray) {
foreach ($monthArray as $day => $dailyEventsArray) {
foreach ($dailyEventsArray as $vevent) {
/** @var $vevent vevent */
$start = "";
$rrule = "NULL";
$allday = 0;
$dtstart = $vevent->getProperty('X-CURRENT-DTSTART');
if (is_array($dtstart)) {
$start = "'" . $dtstart[1] . "'";
if (strpos($dtstart[1], ":") === false) $allday = 1;
} else {
$dtstart = $vevent->getProperty('dtstart');
if (isset($dtstart["day"]) && $dtstart["day"] == $day) { // Mehrtägige Events nur einmal rein
if (isset($dtstart["hour"])) $start = "'" . $dtstart["year"] . "-" . $dtstart["month"] . "-" . $dtstart["day"] . " " . $dtstart["hour"] . ":" . $dtstart["minute"] . ":" . $dtstart["secont"] . "'";
else {
$start = "'" . $dtstart["year"] . "-" . $dtstart["month"] . "-" . $dtstart["day"] . " 00:00:00'";
$allday = 1;
}
}
}
$dtend = $vevent->getProperty('X-CURRENT-DTEND');
if (is_array($dtend)) {
$end = "'" . $dtend[1] . "'";
if (strpos($dtend[1], ":") === false) $allday = 1;
} else {
$dtend = $vevent->getProperty('dtend');
if (isset($dtend["hour"])) $end = "'" . $dtend["year"] . "-" . $dtend["month"] . "-" . $dtend["day"] . " " . $dtend["hour"] . ":" . $dtend["minute"] . ":" . $dtend["second"] . "'";
else {
$end = "'" . $dtend["year"] . "-" . $dtend["month"] . "-" . $dtend["day"] . " 00:00:00' - INTERVAL 1 SECOND";
$allday = 1;
}
}
$summary = $vevent->getProperty('summary');
$description = $vevent->getProperty('description');
$location = $vevent->getProperty('location');
$rrule_prob = $vevent->getProperty('rrule');
if ($rrule_prob != null) {
$rrule = $vevent->createRrule();
$rrule = "'" . dbesc($rrule) . "'";
}
$color_ = $vevent->getProperty("X-ANIMEXX-COLOR");
$color = (is_array($color_) ? $color_[1] : "NULL");
if ($start_min == "" || preg_replace("/[^0-9]/", "", $start) < preg_replace("/[^0-9]/", "", $start_min)) $start_min = $start;
if ($end_max == "" || preg_replace("/[^0-9]/", "", $end) > preg_replace("/[^0-9]/", "", $start_min)) $end_max = $end;
}
}
/**
* @param Sabre_VObject_Component_VEvent $vObject
* @return Sabre_VObject_Component_VEvent|null
*/
function dav_get_eventComponent(&$vObject)
{
$component = null;
$componentType = "";
foreach ($vObject->getComponents() as $component) {
if ($component->name !== 'VTIMEZONE') {
$componentType = $component->name;
break;
}
}
if ($componentType != "VEVENT") return null;
if ($start_min != "") {
if ($allday && mb_strlen($end_max) == 12) {
$x = explode("-", str_replace("'", "", $end_max));
$time = mktime(0, 0, 0, IntVal($x[1]), IntVal($x[2]), IntVal($x[0]));
$end_max = date("'Y-m-d H:i:s'", ($time - 1));
}
q("INSERT INTO %s%sjqcalendar (`uid`, `namespace`, `namespace_id`, `ical_uri`, `Subject`, `Location`, `Description`, `StartTime`, `EndTime`, `IsAllDayEvent`, `RecurringRule`, `Color`)
VALUES (%d, %d, %d, '%s', '%s', '%s', '%s', %s, %s, %d, '%s', '%s')",
CALDAV_SQL_DB, CALDAV_SQL_PREFIX,
IntVal($calendar->uid), IntVal($calendarobject->namespace), IntVal($calendarobject->namespace_id), dbesc($calendarobject->uri), dbesc($summary),
dbesc($location), dbesc(str_replace("\\n", "\n", $description)), $start_min, $end_max, IntVal($allday), dbesc($rrule), dbesc($color)
);
foreach ($vevent->components as $comp) {
/** @var $comp calendarComponent */
$trigger = $comp->getProperty("TRIGGER");
$sql_field = ($trigger["relatedStart"] ? $start : $end);
$sql_op = ($trigger["before"] ? "DATE_SUB" : "DATE_ADD");
$num = "";
$rel_type = "";
$rel_value = 0;
if (isset($trigger["second"])) {
$num = IntVal($trigger["second"]) . " SECOND";
$rel_type = "second";
$rel_value = IntVal($trigger["second"]);
}
if (isset($trigger["minute"])) {
$num = IntVal($trigger["minute"]) . " MINUTE";
$rel_type = "minute";
$rel_value = IntVal($trigger["minute"]);
}
if (isset($trigger["hour"])) {
$num = IntVal($trigger["hour"]) . " HOUR";
$rel_type = "hour";
$rel_value = IntVal($trigger["hour"]);
}
if (isset($trigger["day"])) {
$num = IntVal($trigger["day"]) . " DAY";
$rel_type = "day";
$rel_value = IntVal($trigger["day"]);
}
if (isset($trigger["week"])) {
$num = IntVal($trigger["week"]) . " WEEK";
$rel_type = "week";
$rel_value = IntVal($trigger["week"]);
}
if (isset($trigger["month"])) {
$num = IntVal($trigger["month"]) . " MONTH";
$rel_type = "month";
$rel_value = IntVal($trigger["month"]);
}
if (isset($trigger["year"])) {
$num = IntVal($trigger["year"]) . " YEAR";
$rel_type = "year";
$rel_value = IntVal($trigger["year"]);
}
if ($trigger["before"]) $rel_value *= -1;
if ($rel_type != "") {
$not_date = "$sql_op($sql_field, INTERVAL $num)";
q("INSERT INTO %s%snotifications (`uid`, `ical_uri`, `rel_type`, `rel_value`, `alert_date`, `notified`) VALUES ('%s', '%s', '%s', '%s', %s, IF(%s < NOW(), 1, 0))",
CALDAV_SQL_DB, CALDAV_SQL_PREFIX,
IntVal($calendar->uid), dbesc($calendarobject->uri), dbesc($rel_type), IntVal($rel_value), $not_date, $not_date);
}
}
}
return $component;
}
/**
*
*/
function renderAllCalDavEntries()
{
q("DELETE FROM %s%sjqcalendar", CALDAV_SQL_DB, CALDAV_SQL_PREFIX);
q("DELETE FROM %s%snotifications", CALDAV_SQL_DB, CALDAV_SQL_PREFIX);
$calendars = q("SELECT * FROM %s%scalendars", CALDAV_SQL_DB, CALDAV_SQL_PREFIX);
$anz = count($calendars);
$i = 0;
foreach ($calendars as $calendar) {
$cal = new DBClass_friendica_calendars($calendar);
$i++;
if (($i % 100) == 0) echo "$i / $anz\n";
$calobjs = q("SELECT * FROM %s%scalendarobjects WHERE `namespace` = %d AND `namespace_id` = %d",
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendar["namespace"]), IntVal($calendar["namespace_id"]));
foreach ($calobjs as $calobj) {
$obj = new DBClass_friendica_calendarobjects($calobj);
renderCalDavEntry_data($cal, $obj);
}
}
}
/**
* @param string $uri
* @return bool
*/
function renderCalDavEntry_uri($uri)
{
q("DELETE FROM %s%sjqcalendar WHERE `ical_uri` = '%s'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($uri));
q("DELETE FROM %s%snotifications WHERE `ical_uri` = '%s'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($uri));
$calobj = q("SELECT * FROM %s%scalendarobjects WHERE `uri` = '%s'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($uri));
if (count($calobj) == 0) return false;
$cal = new DBClass_friendica_calendarobjects($calobj[0]);
$calendars = q("SELECT * FROM %s%scalendars WHERE `namespace`=%d AND `namespace_id`=%d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($cal->namespace), IntVal($cal->namespace_id));
$calendar = new DBClass_friendica_calendars($calendars[0]);
renderCalDavEntry_data($calendar, $cal);
return true;
}
/**
* @param $user_id
* @return array|DBClass_friendica_calendars[]
*/
function dav_getMyCals($user_id)
{
$d = q("SELECT * FROM %s%scalendars WHERE `uid` = %d ORDER BY `calendarorder` ASC",
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($user_id), CALDAV_NAMESPACE_PRIVATE
);
$cals = array();
foreach ($d as $e) $cals[] = new DBClass_friendica_calendars($e);
return $cals;
}
/**
* @param mixed $obj
* @return string
*/
function wdcal_jsonp_encode($obj)
{
$str = json_encode($obj);
if (isset($_REQUEST["callback"])) {
$str = $_REQUEST["callback"] . "(" . $str . ")";
}
return $str;
}
/**
* @param string $day
* @param int $weekstartday
* @param int $num_days
* @param string $type
* @return array
*/
function wdcal_get_list_range_params($day, $weekstartday, $num_days, $type)
{
$phpTime = IntVal($day);
switch ($type) {
case "month":
$st = mktime(0, 0, 0, date("m", $phpTime), 1, date("Y", $phpTime));
$et = mktime(0, 0, -1, date("m", $phpTime) + 1, 1, date("Y", $phpTime));
break;
case "week":
//suppose first day of a week is monday
$monday = date("d", $phpTime) - date('N', $phpTime) + 1;
//echo date('N', $phpTime);
$st = mktime(0, 0, 0, date("m", $phpTime), $monday, date("Y", $phpTime));
$et = mktime(0, 0, -1, date("m", $phpTime), $monday + 7, date("Y", $phpTime));
break;
case "multi_days":
//suppose first day of a week is monday
$monday = date("d", $phpTime) - date('N', $phpTime) + $weekstartday;
//echo date('N', $phpTime);
$st = mktime(0, 0, 0, date("m", $phpTime), $monday, date("Y", $phpTime));
$et = mktime(0, 0, -1, date("m", $phpTime), $monday + $num_days, date("Y", $phpTime));
break;
case "day":
$st = mktime(0, 0, 0, date("m", $phpTime), date("d", $phpTime), date("Y", $phpTime));
$et = mktime(0, 0, -1, date("m", $phpTime), date("d", $phpTime) + 1, date("Y", $phpTime));
break;
default:
return array(0, 0);
}
return array($st, $et);
}
/**
* @param string $uri
* @param string $recurr_uri
* @param int $uid
* @param string $timezone
* @param string $goaway_url
* @return string
*/
function wdcal_postEditPage($uri, $recurr_uri = "", $uid = 0, $timezone = "", $goaway_url = "")
{
$uid = IntVal($uid);
$localization = wdcal_local::getInstanceByUser($uid);
if (isset($_REQUEST["allday"])) {
$start = $localization->date_parseLocal($_REQUEST["start_date"] . " 00:00");
$end = $localization->date_parseLocal($_REQUEST["end_date"] . " 20:00");
$isallday = true;
} else {
$start = $localization->date_parseLocal($_REQUEST["start_date"] . " " . $_REQUEST["start_time"]);
$end = $localization->date_parseLocal($_REQUEST["end_date"] . " " . $_REQUEST["end_time"]);
$isallday = false;
}
if ($uri == "new") {
$cals = dav_getMyCals($uid);
foreach ($cals as $c) {
$cs = wdcal_calendar_factory($uid, $c->namespace, $c->namespace_id);
$p = $cs->getPermissionsCalendar($uid);
if ($p["write"]) try {
$cs->addItem($start, $end, dav_compat_getRequestVar("subject"), $isallday, dav_compat_parse_text_serverside("wdcal_desc"),
dav_compat_getRequestVar("location"), dav_compat_getRequestVar("color"), $timezone,
isset($_REQUEST["notification"]), $_REQUEST["notification_type"], $_REQUEST["notification_value"]);
} catch (Exception $e) {
notification(t("Error") . ": " . $e);
}
dav_compat_redirect($goaway_url);
}
} else {
$cals = dav_getMyCals($uid);
foreach ($cals as $c) {
$cs = wdcal_calendar_factory($uid, $c->namespace, $c->namespace_id);
$p = $cs->getPermissionsItem($uid, $uri, $recurr_uri);
if ($p["write"]) try {
$cs->updateItem($uri, $start, $end,
dav_compat_getRequestVar("subject"), $isallday, dav_compat_parse_text_serverside("wdcal_desc"),
dav_compat_getRequestVar("location"), dav_compat_getRequestVar("color"), $timezone,
isset($_REQUEST["notification"]), $_REQUEST["notification_type"], $_REQUEST["notification_value"]);
} catch (Exception $e) {
notification(t("Error") . ": " . $e);
}
dav_compat_redirect($goaway_url);
}
}
}
/**
*
*/
function wdcal_print_feed($base_path = "")
{
$user_id = dav_compat_get_curr_user_id();
$cals = array();
if (isset($_REQUEST["cal"])) foreach ($_REQUEST["cal"] as $c) {
$x = explode("-", $c);
$calendarSource = wdcal_calendar_factory($user_id, $x[0], $x[1]);
$calp = $calendarSource->getPermissionsCalendar($user_id);
if ($calp["read"]) $cals[] = $calendarSource;
}
$ret = null;
/** @var $cals array|AnimexxCalSource[] */
$method = $_GET["method"];
switch ($method) {
case "add":
$cs = null;
foreach ($cals as $c) if ($cs == null) {
$x = $c->getPermissionsCalendar($user_id);
if ($x["read"]) $cs = $c;
}
if ($cs == null) {
echo wdcal_jsonp_encode(array('IsSuccess' => false,
'Msg' => t('No access')));
killme();
}
try {
$start = wdcal_mySql2icalTime(wdcal_php2MySqlTime($_REQUEST["CalendarStartTime"]));
$end = wdcal_mySql2icalTime(wdcal_php2MySqlTime($_REQUEST["CalendarEndTime"]));
$newuri = $cs->addItem($start, $end, $_REQUEST["CalendarTitle"], $_REQUEST["IsAllDayEvent"]);
$ret = array(
'IsSuccess' => true,
'Msg' => 'add success',
'Data' => $newuri,
);
} catch (Exception $e) {
$ret = array(
'IsSuccess' => false,
'Msg' => $e->__toString(),
);
}
break;
case "list":
$weekstartday = (isset($_REQUEST["weekstartday"]) ? IntVal($_REQUEST["weekstartday"]) : 1); // 1 = Monday
$num_days = (isset($_REQUEST["num_days"]) ? IntVal($_REQUEST["num_days"]) : 7);
$ret = null;
$date = wdcal_get_list_range_params($_REQUEST["showdate"], $weekstartday, $num_days, $_REQUEST["viewtype"]);
$ret = array();
$ret['events'] = array();
$ret["issort"] = true;
$ret["start"] = $date[0];
$ret["end"] = $date[1];
$ret['error'] = null;
foreach ($cals as $c) {
$events = $c->listItemsByRange($date[0], $date[1], $base_path);
$ret["events"] = array_merge($ret["events"], $events);
}
$tmpev = array();
foreach ($ret["events"] as $e) {
if (!isset($tmpev[$e["start"]])) $tmpev[$e["start"]] = array();
$tmpev[$e["start"]][] = $e;
}
ksort($tmpev);
$ret["events"] = array();
foreach ($tmpev as $e) foreach ($e as $f) $ret["events"][] = $f;
break;
case "update":
$found = false;
$start = wdcal_mySql2icalTime(wdcal_php2MySqlTime($_REQUEST["CalendarStartTime"]));
$end = wdcal_mySql2icalTime(wdcal_php2MySqlTime($_REQUEST["CalendarEndTime"]));
foreach ($cals as $c) try {
$permissions_item = $c->getPermissionsItem($user_id, $_REQUEST["calendarId"], "");
if ($permissions_item["write"]) {
$c->updateItem($_REQUEST["calendarId"], $start, $end);
$found = true;
}
} catch (Exception $e) {
}
;
if ($found) {
$ret = array(
'IsSuccess' => true,
'Msg' => 'Succefully',
);
} else {
echo wdcal_jsonp_encode(array('IsSuccess' => false,
'Msg' => t('No access')));
killme();
}
try {
} catch (Exception $e) {
$ret = array(
'IsSuccess' => false,
'Msg' => $e->__toString(),
);
}
break;
case "remove":
$found = false;
foreach ($cals as $c) try {
$permissions_item = $c->getPermissionsItem($user_id, $_REQUEST["calendarId"], "");
if ($permissions_item["write"]) $c->removeItem($_REQUEST["calendarId"]);
} catch (Exception $e) {
}
if ($found) {
$ret = array(
'IsSuccess' => true,
'Msg' => 'Succefully',
);
} else {
echo wdcal_jsonp_encode(array('IsSuccess' => false,
'Msg' => t('No access')));
killme();
}
break;
}
echo wdcal_jsonp_encode($ret);
killme();
}

View file

@ -0,0 +1,185 @@
<?php
/**
* @param Sabre_VObject_Component_VAlarm $alarm
* @param Sabre_VObject_Component_VEvent|Sabre_VObject_Component_VTodo $parent
* @return DateTime|null
* @throws Sabre_DAV_Exception
*/
function renderCalDavEntry_calcalarm(&$alarm, &$parent)
{
$trigger = $alarm->__get("TRIGGER");
if (!isset($trigger['VALUE']) || strtoupper($trigger['VALUE']) === 'DURATION') {
$triggerDuration = Sabre_VObject_DateTimeParser::parseDuration($trigger);
$related = (isset($trigger['RELATED']) && strtoupper($trigger['RELATED']) == 'END') ? 'END' : 'START';
if ($related === 'START') {
/** @var Sabre_VObject_Property_DateTime $dtstart */
$dtstart = $parent->__get("DTSTART");
$effectiveTrigger = $dtstart->getDateTime();
$effectiveTrigger->add($triggerDuration);
} else {
if ($parent->name === 'VTODO') {
$endProp = 'DUE';
} else {
$endProp = 'DTEND';
}
/** @var Sabre_VObject_Property_DateTime $dtstart */
$dtstart = $parent->__get("DTSTART");
if (isset($parent->$endProp)) {
$effectiveTrigger = clone $parent->$endProp->getDateTime();
$effectiveTrigger->add($triggerDuration);
} elseif ($parent->__get("DURATION") != "") {
$effectiveTrigger = clone $dtstart->getDateTime();
$duration = Sabre_VObject_DateTimeParser::parseDuration($parent->__get("DURATION"));
$effectiveTrigger->add($duration);
$effectiveTrigger->add($triggerDuration);
} else {
$effectiveTrigger = clone $dtstart->getDateTime();
$effectiveTrigger->add($triggerDuration);
}
}
} else {
// ??? @TODO
$effectiveTrigger = $trigger->getDateTime();
}
return $effectiveTrigger;
}
/**
* @param array $calendar
* @param array $calendarobject
* @throws Sabre_DAV_Exception_BadRequest
* @return void
*/
function renderCalDavEntry_data(&$calendar, &$calendarobject)
{
/** @var Sabre_VObject_Component_VCalendar $vObject */
$vObject = Sabre_VObject_Reader::read($calendarobject["calendardata"]);
$componentType = null;
/** @var Sabre_VObject_Component_VEvent $component */
$component = null;
foreach ($vObject->getComponents() as $component) {
if ($component->name !== 'VTIMEZONE') {
$componentType = $component->name;
break;
}
}
if (!$componentType) {
throw new Sabre_DAV_Exception_BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component');
}
if ($componentType !== 'VEVENT') return;
$event = array(
"description" => ($component->__get("DESCRIPTION") ? $component->__get("DESCRIPTION")->value : null),
"summary" => ($component->__get("SUMMARY") ? $component->__get("SUMMARY")->value : null),
"location" => ($component->__get("LOCATION") ? $component->__get("LOCATION")->value : null),
"color" => ($component->__get("X-ANIMEXX-COLOR") ? $component->__get("X-ANIMEXX-COLOR")->value : null),
);
$recurring = ($component->__get("RRULE") ? 1 : 0);
/** @var Sabre_VObject_Property_DateTime $dtstart */
$dtstart = $component->__get("DTSTART");
$allday = ($dtstart->getDateType() == Sabre_VObject_Property_DateTime::DATE ? 1 : 0);
/** @var array|Sabre_VObject_Component_VAlarm[] $alarms */
$alarms = array();
foreach ($component->getComponents() as $a_component) if ($a_component->name == "VALARM") {
/** var Sabre_VObject_Component_VAlarm $component */
$alarms[] = $a_component;
}
$it = new Sabre_VObject_RecurrenceIterator($vObject, (string)$component->__get("UID"));
$last_end = 0;
$max_ts = mktime(0, 0, 0, 1, 1, CALDAV_MAX_YEAR * 1);
$first = true;
while ($it->valid() && $last_end < $max_ts && ($recurring || $first)) {
$first = false;
$last_end = $it->getDtEnd()->getTimestamp();
$start = $it->getDtStart()->getTimestamp();
q("INSERT INTO %s%sjqcalendar (`calendar_id`, `calendarobject_id`, `Summary`, `StartTime`, `EndTime`, `IsEditable`, `IsAllDayEvent`, `IsRecurring`, `Color`) VALUES
(%d, %d, '%s', '%s', '%s', %d, %d, %d, '%s')", CALDAV_SQL_DB, CALDAV_SQL_PREFIX,
IntVal($calendar["id"]), IntVal($calendarobject["id"]), dbesc($event["summary"]), date("Y-m-d H:i:s", $start), date("Y-m-d H:i:s", $last_end),
1, $allday, $recurring, dbesc(substr($event["color"], 1))
);
foreach ($alarms as $alarm) {
$alarm = renderCalDavEntry_calcalarm($alarm, $component);
$notified = ($alarm->getTimestamp() < time() ? 1 : 0);
q("INSERT INTO %s%snotifications (`calendar_id`, `calendarobject_id`, `alert_date`, `notified`) VALUES (%d, %d, '%s', %d)",
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendar["id"]), IntVal($calendarobject["id"]), $alarm->format("Y-m-d H:i:s"), $notified
);
}
$it->next();
}
return;
}
/**
*
*/
function renderAllCalDavEntries()
{
q("DELETE FROM %s%sjqcalendar", CALDAV_SQL_DB, CALDAV_SQL_PREFIX);
q("DELETE FROM %s%snotifications", CALDAV_SQL_DB, CALDAV_SQL_PREFIX);
$calendars = q("SELECT * FROM %s%scalendars", CALDAV_SQL_DB, CALDAV_SQL_PREFIX);
$anz = count($calendars);
$i = 0;
foreach ($calendars as $calendar) {
$i++;
if (($i % 100) == 0) echo "$i / $anz\n";
$calobjs = q("SELECT * FROM %s%scalendarobjects WHERE `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendar["id"]));
foreach ($calobjs as $calobj) renderCalDavEntry_data($calendar, $calobj);
}
}
/**
* @param string $uri
* @return bool
*/
function renderCalDavEntry_uri($uri)
{
$calobj = q("SELECT * FROM %s%scalendarobjects WHERE `uri` = '%s'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($uri));
if (count($calobj) == 0) return false;
q("DELETE FROM %s%sjqcalendar WHERE `calendar_id` = %d AND `calendarobject_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calobj[0]["calendar_id"]), IntVal($calobj[0]["id"]));
q("DELETE FROM %s%snotifications WHERE `calendar_id` = %d AND `calendarobject_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calobj[0]["calendar_id"]), IntVal($calobj[0]["id"]));
$calendars = q("SELECT * FROM %s%scalendars WHERE `id`=%d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calobj[0]["calendar_id"]));
renderCalDavEntry_data($calendars[0], $calobj[0]);
return true;
}
/**
* @param int $calobj_id
* @return bool
*/
function renderCalDavEntry_calobj_id($calobj_id)
{
$calobj_id = IntVal($calobj_id);
q("DELETE FROM %s%sjqcalendar WHERE `calendarobject_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calobj_id);
q("DELETE FROM %s%snotifications WHERE `calendarobject_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calobj_id);
$calobj = q("SELECT * FROM %s%scalendarobjects WHERE `id` = '%d'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calobj_id);
if (count($calobj) == 0) return false;
$calendars = q("SELECT * FROM %s%scalendars WHERE `id`=%d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calobj[0]["calendar_id"]));
renderCalDavEntry_data($calendars[0], $calobj[0]);
return true;
}

View file

@ -1,76 +1,171 @@
<?php
abstract class Sabre_CalDAV_Backend_Common extends Sabre_CalDAV_Backend_Abstract {
abstract class Sabre_CalDAV_Backend_Common extends Sabre_CalDAV_Backend_Abstract
{
/**
* List of CalDAV properties, and how they map to database fieldnames
*
* Add your own properties by simply adding on to this array
*
* @var array
*/
public $propertyMap = array(
'{DAV:}displayname' => 'displayname',
protected $propertyMap = array(
'{DAV:}displayname' => 'displayname',
'{urn:ietf:params:xml:ns:caldav}calendar-description' => 'description',
'{urn:ietf:params:xml:ns:caldav}calendar-timezone' => 'timezone',
'{http://apple.com/ns/ical/}calendar-order' => 'calendarorder',
'{http://apple.com/ns/ical/}calendar-color' => 'calendarcolor',
'{http://apple.com/ns/ical/}calendar-order' => 'calendarorder',
'{http://apple.com/ns/ical/}calendar-color' => 'calendarcolor',
);
/**
* @abstract
* @return int
*/
abstract public function getNamespace();
abstract public function getCalUrlPrefix();
/**
* @param int $namespace
* @param int $namespace_id
* @param int $calendarId
* @param string $sd
* @param string $ed
* @param string $base_path
* @return array
*/
protected function increaseCalendarCtag($namespace, $namespace_id) {
$namespace = IntVal($namespace);
$namespace_id = IntVal($namespace_id);
abstract public function listItemsByRange($calendarId, $sd, $ed, $base_path);
q("UPDATE %s%scalendars SET `ctag` = `ctag` + 1 WHERE `namespace` = %d AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $namespace, $namespace_id);
/**
* @var array
*/
static private $calendarCache = array();
/**
* @var array
*/
static private $calendarObjectCache = array();
/**
* @static
* @param int $calendarId
* @return array
*/
static public function loadCalendarById($calendarId)
{
if (!isset(self::$calendarCache[$calendarId])) {
$c = q("SELECT * FROM %s%scalendars WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId));
self::$calendarCache[$calendarId] = $c[0];
}
return self::$calendarCache[$calendarId];
}
/**
* @static
* @param int $obj_id
* @return array
*/
static public function loadCalendarobjectById($obj_id)
{
if (!isset(self::$calendarObjectCache[$obj_id])) {
$o = q("SELECT * FROM %s%scalendarobjects WHERE `id` = %d",
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($obj_id)
);
self::$calendarObjectCache[$obj_id] = $o[0];
}
return self::$calendarObjectCache[$obj_id];
}
/**
* Returns a list of calendars for a principal.
*
* Every project is an array with the following keys:
* * id, a unique id that will be used by other functions to modify the
* calendar. This can be the same as the uri or a database key.
* * uri, which the basename of the uri with which the calendar is
* accessed.
* * principaluri. The owner of the calendar. Almost always the same as
* principalUri passed to this method.
*
* Furthermore it can contain webdav properties in clark notation. A very
* common one is '{DAV:}displayname'.
*
* @param string $principalUri
* @return array
* @static
* @param Sabre_VObject_Component_VEvent $component
* @return int
*/
public function getCalendarsForUser($principalUri)
public static function getDtEndTimeStamp(&$component)
{
list(,$name) = Sabre_DAV_URLUtil::splitPath($principalUri);
$user_id = dav_compat_username2id($name);
$cals = q("SELECT * FROM %s%scalendars WHERE `uid`=%d AND `namespace` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $user_id, $this->getNamespace());
$ret = array();
foreach ($cals as $cal) {
$dat = array(
"id" => $cal["namespace"] . "-" . $cal["namespace_id"],
"uri" => $this->getCalUrlPrefix() . "-" . $cal["namespace_id"],
"principaluri" => $principalUri,
'{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}getctag' => $cal['ctag']?$cal['ctag']:'0',
"calendar_class" => "Sabre_CalDAV_Calendar",
);
foreach ($this->propertyMap as $key=>$field) $dat[$key] = $cal[$field];
$ret[] = $dat;
/** @var Sabre_VObject_Property_DateTime $dtstart */
$dtstart = $component->__get("DTSTART");
if ($component->__get("DTEND")) {
/** @var Sabre_VObject_Property_DateTime $dtend */
$dtend = $component->__get("DTEND");
return $dtend->getDateTime()->getTimeStamp();
} elseif ($component->__get("DURATION")) {
$endDate = clone $dtstart->getDateTime();
$endDate->add(Sabre_VObject_DateTimeParser::parse($component->__get("DURATION")->value));
return $endDate->getTimeStamp();
} elseif ($dtstart->getDateType() === Sabre_VObject_Property_DateTime::DATE) {
$endDate = clone $dtstart->getDateTime();
$endDate->modify('+1 day');
return $endDate->getTimeStamp();
} else {
return $dtstart->getDateTime()->getTimeStamp() + 3600;
}
return $ret;
}
/**
* Parses some information from calendar objects, used for optimized
* calendar-queries.
*
* Returns an array with the following keys:
* * etag
* * size
* * componentType
* * firstOccurence
* * lastOccurence
*
* @param string $calendarData
* @throws Sabre_DAV_Exception_BadRequest
* @return array
*/
protected function getDenormalizedData($calendarData)
{
/** @var Sabre_VObject_Component_VEvent $vObject */
$vObject = Sabre_VObject_Reader::read($calendarData);
$componentType = null;
$component = null;
$firstOccurence = null;
$lastOccurence = null;
foreach ($vObject->getComponents() as $component) {
if ($component->name !== 'VTIMEZONE') {
$componentType = $component->name;
break;
}
}
if (!$componentType) {
throw new Sabre_DAV_Exception_BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component');
}
if ($componentType === 'VEVENT') {
/** @var Sabre_VObject_Component_VEvent $component */
/** @var Sabre_VObject_Property_DateTime $dtstart */
$dtstart = $component->__get("DTSTART");
$firstOccurence = $dtstart->getDateTime()->getTimeStamp();
// Finding the last occurence is a bit harder
if (!$component->__get("RRULE")) {
$lastOccurence = self::getDtEndTimeStamp($component);
} else {
$it = new Sabre_VObject_RecurrenceIterator($vObject, (string)$component->__get("UID"));
$maxDate = new DateTime(CALDAV_MAX_YEAR . "-01-01");
if ($it->isInfinite()) {
$lastOccurence = $maxDate->getTimeStamp();
} else {
$end = $it->getDtEnd();
while ($it->valid() && $end < $maxDate) {
$end = $it->getDtEnd();
$it->next();
}
$lastOccurence = $end->getTimeStamp();
}
}
}
return array(
'etag' => md5($calendarData),
'size' => strlen($calendarData),
'componentType' => $componentType,
'firstOccurence' => $firstOccurence,
'lastOccurence' => $lastOccurence,
);
}
/**
@ -109,10 +204,11 @@ abstract class Sabre_CalDAV_Backend_Common extends Sabre_CalDAV_Backend_Abstract
* @param array $mutations
* @return bool|array
*/
public function updateCalendar($calendarId, array $mutations) {
public function updateCalendar($calendarId, array $mutations)
{
$newValues = array();
$result = array(
$result = array(
200 => array(), // Ok
403 => array(), // Forbidden
424 => array(), // Failed Dependency
@ -120,17 +216,17 @@ abstract class Sabre_CalDAV_Backend_Common extends Sabre_CalDAV_Backend_Abstract
$hasError = false;
foreach($mutations as $propertyName=>$propertyValue) {
foreach ($mutations as $propertyName=> $propertyValue) {
// We don't know about this property.
if (!isset($this->propertyMap[$propertyName])) {
$hasError = true;
$hasError = true;
$result[403][$propertyName] = null;
unset($mutations[$propertyName]);
continue;
}
$fieldName = $this->propertyMap[$propertyName];
$fieldName = $this->propertyMap[$propertyName];
$newValues[$fieldName] = $propertyValue;
}
@ -138,33 +234,46 @@ abstract class Sabre_CalDAV_Backend_Common extends Sabre_CalDAV_Backend_Abstract
// If there were any errors we need to fail the request
if ($hasError) {
// Properties has the remaining properties
foreach($mutations as $propertyName=>$propertyValue) {
foreach ($mutations as $propertyName=> $propertyValue) {
$result[424][$propertyName] = null;
}
// Removing unused statuscodes for cleanliness
foreach($result as $status=>$properties) {
if (is_array($properties) && count($properties)===0) unset($result[$status]);
foreach ($result as $status=> $properties) {
if (is_array($properties) && count($properties) === 0) unset($result[$status]);
}
return $result;
}
$x = explode("-", $calendarId);
$this->increaseCalendarCtag($x[0], $x[1]);
$this->increaseCalendarCtag($calendarId);
$valuesSql = array();
foreach($newValues as $fieldName=>$value) $valuesSql[] = "`" . $fieldName . "` = '" . dbesc($value) . "'";
foreach ($newValues as $fieldName=> $value) $valuesSql[] = "`" . $fieldName . "` = '" . dbesc($value) . "'";
if (count($valuesSql) > 0) {
q("UPDATE %s%scalendars SET " . implode(", ", $valuesSql) . " WHERE `namespace` = %d AND `namespace_id` = %d",
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($x[0]), IntVal($x[1])
);
q("UPDATE %s%scalendars SET " . implode(", ", $valuesSql) . " WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId));
}
return true;
}
/**
* @param int $calendarId
*/
protected function increaseCalendarCtag($calendarId)
{
q("UPDATE %s%scalendars SET `ctag` = `ctag` + 1 WHERE `id` = '%d'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId));
self::$calendarObjectCache = array();
}
/**
* @abstract
* @param int $calendar_id
* @param int $calendarobject_id
* @return string
*/
abstract function getItemDetailRedirect($calendar_id, $calendarobject_id);
}

View file

@ -0,0 +1,495 @@
<?php
class Sabre_CalDAV_Backend_Private extends Sabre_CalDAV_Backend_Common
{
/**
* @var null|Sabre_CalDAV_Backend_Private
*/
private static $instance = null;
/**
* @static
* @return Sabre_CalDAV_Backend_Private
*/
public static function getInstance()
{
if (self::$instance == null) {
self::$instance = new Sabre_CalDAV_Backend_Private();
}
return self::$instance;
}
/**
* @return int
*/
public function getNamespace()
{
return CALDAV_NAMESPACE_PRIVATE;
}
/**
* @obsolete
* @param array $calendar
* @param int $user
* @return array
*/
public function getPermissionsCalendar($calendar, $user)
{
if ($calendar["namespace"] == CALDAV_NAMESPACE_PRIVATE && $user == $calendar["namespace_id"]) return array("read"=> true, "write"=> true);
return array("read"=> false, "write"=> false);
}
/**
* @obsolete
* @param array $calendar
* @param int $user
* @param string $calendarobject_id
* @param null|array $item_arr
* @return array
*/
public function getPermissionsItem($calendar, $user, $calendarobject_id, $item_arr = null)
{
return $this->getPermissionsCalendar($calendar, $user);
}
/**
* @param array $row
* @param array $calendar
* @param string $base_path
* @return array
*/
private function jqcal2wdcal($row, $calendar, $base_path)
{
$not = q("SELECT COUNT(*) num FROM %s%snotifications WHERE `calendar_id` = %d AND `calendarobject_id` = %d",
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($row["calendar_id"]), IntVal($row["calendarobject_id"])
);
$editable = $this->getPermissionsItem($calendar["namespace_id"], $row["calendarobject_id"], $row);
$end = wdcal_mySql2PhpTime($row["EndTime"]);
if ($row["IsAllDayEvent"]) $end -= 1;
return array(
"jq_id" => $row["id"],
"ev_id" => $row["calendarobject_id"],
"summary" => escape_tags($row["Summary"]),
"start" => wdcal_mySql2PhpTime($row["StartTime"]),
"end" => $end,
"is_allday" => $row["IsAllDayEvent"],
"is_moredays" => 0,
"is_recurring" => $row["IsRecurring"],
"color" => (is_null($row["Color"]) || $row["Color"] == "" ? $calendar["calendarcolor"] : $row["Color"]),
"is_editable" => ($editable ? 1 : 0),
"is_editable_quick" => ($editable && !$row["IsRecurring"] ? 1 : 0),
"location" => "Loc.",
"attendees" => '',
"has_notification" => ($not[0]["num"] > 0 ? 1 : 0),
"url_detail" => $base_path . $row["calendarobject_id"] . "/",
"url_edit" => $base_path . $row["calendarobject_id"] . "/edit/",
"special_type" => "",
);
}
/**
* @param int $calendarId
* @param string $sd
* @param string $ed
* @param string $base_path
* @return array
*/
public function listItemsByRange($calendarId, $sd, $ed, $base_path)
{
$calendar = Sabre_CalDAV_Backend_Common::loadCalendarById($calendarId);
$von = wdcal_php2MySqlTime($sd);
$bis = wdcal_php2MySqlTime($ed);
// @TODO Events, die früher angefangen haben, aber noch andauern
$evs = q("SELECT * FROM %s%sjqcalendar WHERE `calendar_id` = %d AND `starttime` between '%s' and '%s'",
CALDAV_SQL_DB, CALDAV_SQL_PREFIX,
IntVal($calendarId), dbesc($von), dbesc($bis));
$events = array();
foreach ($evs as $row) $events[] = $this->jqcal2wdcal($row, $calendar, $base_path . $row["calendar_id"] . "/");
return $events;
}
/**
* @param int $calendar_id
* @param int $calendarobject_id
* @return string
*/
public function getItemDetailRedirect($calendar_id, $calendarobject_id)
{
return "/dav/wdcal/$calendar_id/$calendarobject_id/edit/";
}
/**
* Returns a list of calendars for a principal.
*
* Every project is an array with the following keys:
* * id, a unique id that will be used by other functions to modify the
* calendar. This can be the same as the uri or a database key.
* * uri, which the basename of the uri with which the calendar is
* accessed.
* * principaluri. The owner of the calendar. Almost always the same as
* principalUri passed to this method.
*
* Furthermore it can contain webdav properties in clark notation. A very
* common one is '{DAV:}displayname'.
*
* @param string $principalUri
* @return array
*/
public function getCalendarsForUser($principalUri)
{
$n = dav_compat_principal2namespace($principalUri);
if ($n["namespace"] != $this->getNamespace()) return array();
$cals = q("SELECT * FROM %s%scalendars WHERE `namespace` = %d AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $this->getNamespace(), IntVal($n["namespace_id"]));
$ret = array();
foreach ($cals as $cal) {
if (in_array($cal["uri"], $GLOBALS["CALDAV_PRIVATE_SYSTEM_CALENDARS"])) continue;
$dat = array(
"id" => $cal["id"],
"uri" => $cal["uri"],
"principaluri" => $principalUri,
'{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}getctag' => $cal['ctag'] ? $cal['ctag'] : '0',
"calendar_class" => "Sabre_CalDAV_Calendar",
);
foreach ($this->propertyMap as $key=> $field) $dat[$key] = $cal[$field];
$ret[] = $dat;
}
return $ret;
}
/**
* Creates a new calendar for a principal.
*
* If the creation was a success, an id must be returned that can be used to reference
* this calendar in other methods, such as updateCalendar.
*
* @param string $principalUri
* @param string $calendarUri
* @param array $properties
* @throws Sabre_DAV_Exception
* @return string|void
*/
public function createCalendar($principalUri, $calendarUri, array $properties)
{
$uid = dav_compat_principal2uid($principalUri);
$r = q("SELECT * FROM %s%scalendars WHERE `namespace` = %d AND `namespace_id` = %d AND `uri` = '%s'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CALDAV_NAMESPACE_PRIVATE, $uid, dbesc($calendarUri));
if (count($r) > 0) throw new Sabre_DAV_Exception("A calendar with this URI already exists");
$keys = array("`namespace`", "`namespace_id`", "`ctag`", "`uri`");
$vals = array(CALDAV_NAMESPACE_PRIVATE, IntVal($uid), 1, "'" . dbesc($calendarUri) . "'");
// Default value
$sccs = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set';
$has_vevent = $has_vtodo = 1;
if (isset($properties[$sccs])) {
if (!($properties[$sccs] instanceof Sabre_CalDAV_Property_SupportedCalendarComponentSet)) {
throw new Sabre_DAV_Exception('The ' . $sccs . ' property must be of type: Sabre_CalDAV_Property_SupportedCalendarComponentSet');
}
$v = $properties[$sccs]->getValue();
$has_vevent = $has_vtodo = 0;
foreach ($v as $w) {
if (mb_strtolower($w) == "vevent") $has_vevent = 1;
if (mb_strtolower($w) == "vtodo") $has_vtodo = 1;
}
}
$keys[] = "`has_vevent`";
$keys[] = "`has_vtodo`";
$vals[] = $has_vevent;
$vals[] = $has_vtodo;
foreach ($this->propertyMap as $xmlName=> $dbName) {
if (isset($properties[$xmlName])) {
$keys[] = "`$dbName`";
$vals[] = "'" . dbesc($properties[$xmlName]) . "'";
}
}
$sql = sprintf("INSERT INTO %s%scalendars (" . implode(', ', $keys) . ") VALUES (" . implode(', ', $vals) . ")", CALDAV_SQL_DB, CALDAV_SQL_PREFIX);
q($sql);
$x = q("SELECT id FROM %s%scalendars WHERE `namespace` = %d AND `namespace_id` = %d AND `uri` = '%s'",
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CALDAV_NAMESPACE_PRIVATE, $uid, $calendarUri
);
return $x[0]["id"];
}
/**
* Updates properties for a calendar.
*
* The mutations array uses the propertyName in clark-notation as key,
* and the array value for the property value. In the case a property
* should be deleted, the property value will be null.
*
* This method must be atomic. If one property cannot be changed, the
* entire operation must fail.
*
* If the operation was successful, true can be returned.
* If the operation failed, false can be returned.
*
* Deletion of a non-existent property is always successful.
*
* Lastly, it is optional to return detailed information about any
* failures. In this case an array should be returned with the following
* structure:
*
* array(
* 403 => array(
* '{DAV:}displayname' => null,
* ),
* 424 => array(
* '{DAV:}owner' => null,
* )
* )
*
* In this example it was forbidden to update {DAV:}displayname.
* (403 Forbidden), which in turn also caused {DAV:}owner to fail
* (424 Failed Dependency) because the request needs to be atomic.
*
* @param string $calendarId
* @param array $mutations
* @return bool|array
*/
public function updateCalendar($calendarId, array $mutations)
{
$newValues = array();
$result = array(
200 => array(), // Ok
403 => array(), // Forbidden
424 => array(), // Failed Dependency
);
$hasError = false;
foreach ($mutations as $propertyName=> $propertyValue) {
// We don't know about this property.
if (!isset($this->propertyMap[$propertyName])) {
$hasError = true;
$result[403][$propertyName] = null;
unset($mutations[$propertyName]);
continue;
}
$fieldName = $this->propertyMap[$propertyName];
$newValues[$fieldName] = $propertyValue;
}
// If there were any errors we need to fail the request
if ($hasError) {
// Properties has the remaining properties
foreach ($mutations as $propertyName=> $propertyValue) {
$result[424][$propertyName] = null;
}
// Removing unused statuscodes for cleanliness
foreach ($result as $status=> $properties) {
if (is_array($properties) && count($properties) === 0) unset($result[$status]);
}
return $result;
}
$sql = "`ctag` = `ctag` + 1";
foreach ($newValues as $key=> $val) $sql .= ", `" . $key . "` = '" . dbesc($val) . "'";
$sql = sprintf("UPDATE %s%scalendars SET $sql WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId));
q($sql);
return true;
}
/**
* Delete a calendar and all it's objects
*
* @param string $calendarId
* @return void
*/
public function deleteCalendar($calendarId)
{
q("DELETE FROM %s%scalendarobjects WHERE `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId));
q("DELETE FROM %s%scalendars WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId));
}
/**
* Returns all calendar objects within a calendar.
*
* Every item contains an array with the following keys:
* * id - unique identifier which will be used for subsequent updates
* * calendardata - The iCalendar-compatible calendar data
* * uri - a unique key which will be used to construct the uri. This can be any arbitrary string.
* * lastmodified - a timestamp of the last modification time
* * etag - An arbitrary string, surrounded by double-quotes. (e.g.:
* ' "abcdef"')
* * calendarid - The calendarid as it was passed to this function.
* * size - The size of the calendar objects, in bytes.
*
* Note that the etag is optional, but it's highly encouraged to return for
* speed reasons.
*
* The calendardata is also optional. If it's not returned
* 'getCalendarObject' will be called later, which *is* expected to return
* calendardata.
*
* If neither etag or size are specified, the calendardata will be
* used/fetched to determine these numbers. If both are specified the
* amount of times this is needed is reduced by a great degree.
*
* @param mixed $calendarId
* @return array
*/
function getCalendarObjects($calendarId)
{
$objs = q("SELECT * FROM %s%scalendarobjects WHERE `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId));
$ret = array();
foreach ($objs as $obj) {
$ret[] = array(
"id" => IntVal($obj["id"]),
"calendardata" => $obj["calendardata"],
"uri" => $obj["uri"],
"lastmodified" => $obj["lastmodified"],
"calendarid" => $calendarId,
"etag" => $obj["etag"],
"size" => IntVal($obj["size"]),
);
}
return $ret;
}
/**
* Returns information from a single calendar object, based on it's object
* uri.
*
* The returned array must have the same keys as getCalendarObjects. The
* 'calendardata' object is required here though, while it's not required
* for getCalendarObjects.
*
* @param string $calendarId
* @param string $objectUri
* @throws Sabre_DAV_Exception_NotFound
* @return array
*/
function getCalendarObject($calendarId, $objectUri)
{
$o = q("SELECT * FROM %s%scalendarobjects WHERE `calendar_id` = %d AND `uri` = '%s'",
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId), dbesc($objectUri));
if (count($o) > 0) {
$o[0]["calendarid"] = $calendarId;
$o[0]["calendardata"] = str_ireplace("Europe/Belgrade", "Europe/Berlin", $o[0]["calendardata"]);
return $o[0];
} else throw new Sabre_DAV_Exception_NotFound($calendarId . " / " . $objectUri);
}
/**
* Creates a new calendar object.
*
* It is possible return an etag from this function, which will be used in
* the response to this PUT request. Note that the ETag must be surrounded
* by double-quotes.
*
* However, you should only really return this ETag if you don't mangle the
* calendar-data. If the result of a subsequent GET to this object is not
* the exact same as this request body, you should omit the ETag.
*
* @param mixed $calendarId
* @param string $objectUri
* @param string $calendarData
* @return string|null
*/
function createCalendarObject($calendarId, $objectUri, $calendarData)
{
$calendarData = icalendar_sanitize_string($calendarData);
$extraData = $this->getDenormalizedData($calendarData);
q("INSERT INTO %s%scalendarobjects (`calendar_id`, `uri`, `calendardata`, `lastmodified`, `componentType`, `firstOccurence`, `lastOccurence`, `etag`, `size`)
VALUES (%d, '%s', '%s', NOW(), '%s', '%s', '%s', '%s', %d)",
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId), dbesc($objectUri), addslashes($calendarData), dbesc($extraData['componentType']),
dbesc(wdcal_php2MySqlTime($extraData['firstOccurence'])), dbesc(wdcal_php2MySqlTime($extraData['lastOccurence'])), dbesc($extraData["etag"]), IntVal($extraData["size"])
);
$this->increaseCalendarCtag($calendarId);
renderCalDavEntry_uri($objectUri);
return '"' . $extraData['etag'] . '"';
}
/**
* Updates an existing calendarobject, based on it's uri.
*
* It is possible return an etag from this function, which will be used in
* the response to this PUT request. Note that the ETag must be surrounded
* by double-quotes.
*
* However, you should only really return this ETag if you don't mangle the
* calendar-data. If the result of a subsequent GET to this object is not
* the exact same as this request body, you should omit the ETag.
*
* @param mixed $calendarId
* @param string $objectUri
* @param string $calendarData
* @return string|null
*/
function updateCalendarObject($calendarId, $objectUri, $calendarData)
{
$calendarData = icalendar_sanitize_string($calendarData);
$extraData = $this->getDenormalizedData($calendarData);
q("UPDATE %s%scalendarobjects SET `calendardata` = '%s', `lastmodified` = NOW(), `etag` = '%s', `size` = %d, `componentType` = '%s', `firstOccurence` = '%s', `lastOccurence` = '%s'
WHERE `calendar_id` = %d AND `uri` = '%s'",
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($calendarData), dbesc($extraData["etag"]), IntVal($extraData["size"]), dbesc($extraData["componentType"]),
dbesc(wdcal_php2MySqlTime($extraData["firstOccurence"])), dbesc(wdcal_php2MySqlTime($extraData["lastOccurence"])), IntVal($calendarId), dbesc($objectUri));
$this->increaseCalendarCtag($calendarId);
renderCalDavEntry_uri($objectUri);
return '"' . $extraData['etag'] . '"';
}
/**
* Deletes an existing calendar object.
*
* @param string $calendarId
* @param string $objectUri
* @throws Sabre_DAV_Exception_NotFound
* @return void
*/
function deleteCalendarObject($calendarId, $objectUri)
{
$r = q("SELECT `id` FROM %s%scalendarobjects WHERE `calendar_id` = %d AND `uri` = '%s'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId), dbesc($objectUri));
if (count($r) == 0) throw new Sabre_DAV_Exception_NotFound();
q("DELETE FROM %s%scalendarobjects WHERE `calendar_id` = %d AND `uri` = '%s'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId), dbesc($objectUri));
$this->increaseCalendarCtag($calendarId);
renderCalDavEntry_calobj_id($r[0]["id"]);
}
}

View file

@ -0,0 +1,186 @@
<?php
abstract class Sabre_CalDAV_Backend_Virtual extends Sabre_CalDAV_Backend_Common
{
/**
* @static
* @abstract
* @param int $calendarId
* @param string $uri
* @return array
*/
/*
abstract public function getItemsByUri($calendarId, $uri);
*/
/**
* @static
* @param int $uid
* @param int $namespace
*/
static public function invalidateCache($uid = 0, $namespace = 0) {
q("DELETE FROM %s%scal_virtual_object_sync WHERE `uid` = %d AND `namespace` = %d",
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($uid), IntVal($namespace));
}
/**
* @static
* @abstract
* @param int $calendarId
*/
static abstract protected function createCache_internal($calendarId);
/**
* @static
* @param int $calendarId
*/
static protected function createCache($calendarId) {
$calendarId = IntVal($calendarId);
q("DELETE FROM %s%scal_virtual_object_cache WHERE `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendarId);
static::createCache_internal($calendarId);
q("REPLACE INTO %s%scal_virtual_object_sync (`calendar_id`, `date`) VALUES (%d, NOW())", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendarId);
}
/**
* @param string $calendarId
* @return array
*/
public function getCalendarObjects($calendarId)
{
$calendarId = IntVal($calendarId);
$r = q("SELECT COUNT(*) n FROM %s%scal_virtual_object_sync WHERE `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendarId);
if ($r[0]["n"] == 0) static::createCache($calendarId);
$r = q("SELECT * FROM %s%scal_virtual_object_cache WHERE `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendarId);
$ret = array();
foreach ($r as $obj) {
$ret[] = array(
"id" => IntVal($obj["data_uri"]),
"calendardata" => $obj["calendardata"],
"uri" => $obj["data_uri"],
"lastmodified" => $obj["date"],
"calendarid" => $calendarId,
"etag" => $obj["etag"],
"size" => IntVal($obj["size"]),
);
}
return $ret;
}
/**
* Returns information from a single calendar object, based on it's object
* uri.
*
* The returned array must have the same keys as getCalendarObjects. The
* 'calendardata' object is required here though, while it's not required
* for getCalendarObjects.
*
* @param string $calendarId
* @param string $objectUri
* @throws Sabre_DAV_Exception_NotFound
* @return array
*/
public function getCalendarObject($calendarId, $objectUri)
{
$calendarId = IntVal($calendarId);
$r = q("SELECT COUNT(*) n FROM %s%scal_virtual_object_sync WHERE `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendarId));
if ($r[0]["n"] == 0) static::createCache($calendarId);
$r = q("SELECT * FROM %s%scal_virtual_object_cache WHERE `data_uri` = '%s' AND `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($objectUri), IntVal($calendarId));
if (count($r) == 0) throw new Sabre_DAV_Exception_NotFound();
$obj = $r[0];
$ret = array(
"id" => IntVal($obj["data_uri"]),
"calendardata" => $obj["calendardata"],
"uri" => $obj["data_uri"],
"lastmodified" => $obj["date"],
"calendarid" => $calendarId,
"etag" => $obj["etag"],
"size" => IntVal($obj["size"]),
);
return $ret;
}
/**
* Creates a new calendar for a principal.
*
* If the creation was a success, an id must be returned that can be used to reference
* this calendar in other methods, such as updateCalendar.
*
* @param string $principalUri
* @param string $calendarUri
* @param array $properties
* @throws Sabre_DAV_Exception_Forbidden
* @return void
*/
public function createCalendar($principalUri, $calendarUri, array $properties)
{
throw new Sabre_DAV_Exception_Forbidden();
}
/**
* Delete a calendar and all it's objects
*
* @param string $calendarId
* @throws Sabre_DAV_Exception_Forbidden
* @return void
*/
public function deleteCalendar($calendarId)
{
throw new Sabre_DAV_Exception_Forbidden();
}
/**
* Creates a new calendar object.
*
* @param string $calendarId
* @param string $objectUri
* @param string $calendarData
* @throws Sabre_DAV_Exception_Forbidden
* @return null|string|void
*/
function createCalendarObject($calendarId, $objectUri, $calendarData)
{
throw new Sabre_DAV_Exception_Forbidden();
}
/**
* Updates an existing calendarobject, based on it's uri.
*
* @param string $calendarId
* @param string $objectUri
* @param string $calendarData
* @throws Sabre_DAV_Exception_Forbidden
* @return null|string|void
*/
function updateCalendarObject($calendarId, $objectUri, $calendarData)
{
throw new Sabre_DAV_Exception_Forbidden();
}
/**
* Deletes an existing calendar object.
*
* @param string $calendarId
* @param string $objectUri
* @throws Sabre_DAV_Exception_Forbidden
* @return void
*/
function deleteCalendarObject($calendarId, $objectUri)
{
throw new Sabre_DAV_Exception_Forbidden();
}
}

View file

@ -0,0 +1,44 @@
<?php
class Sabre_CalDAV_Calendar_Virtual extends Sabre_CalDAV_Calendar {
/**
* Returns a list of ACE's for this node.
*
* Each ACE has the following properties:
* * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
* currently the only supported privileges
* * 'principal', a url to the principal who owns the node
* * 'protected' (optional), indicating that this ACE is not allowed to
* be updated.
*
* @return array
*/
public function getACL() {
return array(
array(
'privilege' => '{DAV:}read',
'principal' => $this->calendarInfo['principaluri'],
'protected' => true,
),
array(
'privilege' => '{DAV:}read',
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
'protected' => true,
),
array(
'privilege' => '{DAV:}read',
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read',
'protected' => true,
),
array(
'privilege' => '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}read-free-busy',
'principal' => '{DAV:}authenticated',
'protected' => true,
),
);
}
}

View file

@ -14,6 +14,23 @@
class Sabre_CardDAV_Backend_Std extends Sabre_CardDAV_Backend_Abstract
{
/**
* @var null|Sabre_CardDAV_Backend_Std
*/
private static $instance = null;
/**
* @static
* @return Sabre_CardDAV_Backend_Std
*/
public static function getInstance() {
if (self::$instance == null) {
self::$instance = new Sabre_CardDAV_Backend_Std();
}
return self::$instance;
}
/**
* Sets up the object
*/

View file

@ -1,14 +1,6 @@
<?php
/**
* The UserCalenders class contains all calendars associated to one user
*
* @package Sabre
* @subpackage CalDAV
* @copyright Copyright (C) 2007-2011 Rooftop Solutions. All rights reserved.
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
*/
class Sabre_CalDAV_AnimexxUserCalendars implements Sabre_DAV_IExtendedCollection, Sabre_DAVACL_IACL {
/**
@ -21,7 +13,7 @@ class Sabre_CalDAV_AnimexxUserCalendars implements Sabre_DAV_IExtendedCollection
/**
* CalDAV backends
*
* @var array|Sabre_CalDAV_Backend_Abstract[]
* @var array|Sabre_CalDAV_Backend_Common[]
*/
protected $caldavBackends;
@ -36,7 +28,7 @@ class Sabre_CalDAV_AnimexxUserCalendars implements Sabre_DAV_IExtendedCollection
* Constructor
*
* @param Sabre_DAVACL_IPrincipalBackend $principalBackend
* @param array|Sabre_CalDAV_Backend_Abstract $caldavBackends
* @param array|Sabre_CalDAV_Backend_Common[] $caldavBackends
* @param mixed $userUri
*/
public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, $caldavBackends, $userUri) {
@ -130,7 +122,7 @@ class Sabre_CalDAV_AnimexxUserCalendars implements Sabre_DAV_IExtendedCollection
* Returns a single calendar, by name
*
* @param string $name
* @throws Sabre_DAV_Exception_FileNotFound
* @throws Sabre_DAV_Exception_NotFound
* @todo needs optimizing
* @return \Sabre_CalDAV_Calendar|\Sabre_DAV_INode
*/
@ -141,7 +133,7 @@ class Sabre_CalDAV_AnimexxUserCalendars implements Sabre_DAV_IExtendedCollection
return $child;
}
throw new Sabre_DAV_Exception_FileNotFound('Calendar with name \'' . $name . '\' could not be found');
throw new Sabre_DAV_Exception_NotFound('Calendar with name \'' . $name . '\' could not be found');
}

View file

@ -16,16 +16,19 @@ function wdcal_edit_getStartEnd() {
function wdcal_edit_checktime_startChanged() {
"use strict";
var time = wdcal_edit_getStartEnd();
if (time.start.getTime() >= time.end.getTime()) {
var newend = new Date(time.start.getTime() + 3600000);
$("#cal_end_date").datepicker("setDate", newend);
$.timePicker("#cal_end_time").setTime(newend);
}
wdcal_edit_recur_recalc();
}
function wdcal_edit_checktime_endChanged() {
"use strict";
var time = wdcal_edit_getStartEnd();
if (time.start.getTime() >= time.end.getTime()) {
var newstart = new Date(time.end.getTime() - 3600000);
@ -34,7 +37,27 @@ function wdcal_edit_checktime_endChanged() {
}
}
function wdcal_edit_init(dateFormat) {
function wdcal_edit_recur_recalc() {
"use strict";
var start = $("#cal_start_date").datepicker("getDate");
$(".rec_month_name").text($.datepicker._defaults.monthNames[start.getMonth()]);
$("#rec_yearly_day option[value=bymonthday], #rec_monthly_day option[value=bymonthday]").text($("#rec_yearly_day option[value=bymonthday]").data("orig").replace("#num#", start.getDate()));
var month = new Date(start.getFullYear(), start.getMonth() + 1, 0);
var monthlast = month.getDate() - start.getDate() + 1;
$("#rec_yearly_day option[value=bymonthday_neg], #rec_monthly_day option[value=bymonthday_neg]").text($("#rec_yearly_day option[value=bymonthday_neg]").data("orig").replace("#num#", monthlast));
var wk = Math.ceil(start.getDate() / 7);
var wkname = $.datepicker._defaults.dayNames[start.getDay()];
$("#rec_yearly_day option[value=byday], #rec_monthly_day option[value=byday]").text(
$("#rec_yearly_day option[value=byday]").data("orig").replace("#num#", wk).replace("#wkday#", wkname)
);
var wk_inv = Math.ceil(monthlast / 7);
$("#rec_yearly_day option[value=byday_neg], #rec_monthly_day option[value=byday_neg]").text(
$("#rec_yearly_day option[value=byday_neg]").data("orig").replace("#num#", wk_inv).replace("#wkday#", wkname)
);
}
function wdcal_edit_init(dateFormat, base_path) {
"use strict";
$("#cal_color").colorPicker();
@ -49,6 +72,8 @@ function wdcal_edit_init(dateFormat) {
"dateFormat": dateFormat
}).on("change", wdcal_edit_checktime_endChanged);
$("#rec_until_date").datepicker({ "dateFormat": dateFormat });
$("#notification").on("click change", function() {
if ($(this).prop("checked")) $("#notification_detail").show();
else ($("#notification_detail")).hide();
@ -58,4 +83,111 @@ function wdcal_edit_init(dateFormat) {
if ($(this).prop("checked")) $("#cal_end_time, #cal_start_time").hide();
else $("#cal_end_time, #cal_start_time").show();
}).change();
$("#rec_frequency").on("click change", function() {
var val = $("#rec_frequency").val();
if (val == "") $("#rec_details").hide();
else $("#rec_details").show();
if (val == "daily") $(".rec_daily").show();
else $(".rec_daily").hide();
if (val == "weekly") $(".rec_weekly").show();
else $(".rec_weekly").hide();
if (val == "monthly") $(".rec_monthly").show();
else $(".rec_monthly").hide();
if (val == "yearly") $(".rec_yearly").show();
else $(".rec_yearly").hide();
}).change();
$("#rec_until_type").on("click change", function() {
var val = $("#rec_until_type").val();
if (val == "count") $("#rec_until_count").show();
else $("#rec_until_count").hide();
if (val == "date") $("#rec_until_date").show();
else $("#rec_until_date").hide();
}).change();
$("#rec_yearly_day option, #rec_monthly_day option").each(function() {
$(this).data("orig", $(this).text());
});
wdcal_edit_recur_recalc();
$(document).on("click", ".exception_remover", function(ev) {
ev.preventDefault();
var $this = $(this),
$par = $this.parents(".rec_exceptions");
$this.parents(".except").remove();
if ($par.find(".rec_exceptions_holder").children().length == 0) {
$par.find(".rec_exceptions_holder").hide();
$par.find(".rec_exceptions_none").show();
}
});
$(".exception_adder").click(function(ev) {
ev.preventDefault();
var exceptions = [];
$(".rec_exceptions .except input").each(function() {
exceptions.push($(this).val());
});
var rec_weekly_byday = [];
$(".rec_weekly_byday:checked").each(function() {
rec_weekly_byday.push($(this).val());
});
var rec_daily_byday = [];
$(".rec_daily_byday:checked").each(function() {
rec_daily_byday.push($(this).val());
});
var opts = {
"start_date": $("input[name=start_date]").val(),
"start_time": $("input[name=start_time]").val(),
"end_date": $("input[name=end_date]").val(),
"end_time": $("input[name=end_time]").val(),
"rec_frequency": $("#rec_frequency").val(),
"rec_interval": $("#rec_interval").val(),
"rec_until_type": $("#rec_until_type").val(),
"rec_until_count": $("#rec_until_count").val(),
"rec_until_date": $("#rec_until_date").val(),
"rec_weekly_byday": rec_weekly_byday,
"rec_daily_byday": rec_daily_byday,
"rec_weekly_wkst": $("input[name=rec_weekly_wkst]:checked").val(),
"rec_monthly_day": $("#rec_monthly_day").val(),
"rec_yearly_day": $("#rec_yearly_day").val(),
"rec_exceptions": exceptions
};
if ($("#cal_allday").prop("checked")) opts["allday"] = 1;
var $dial = $("<div id='exception_setter_dialog'>Loading...</div>");
$dial.appendTo("body");
$dial.dialog({
"width": 400,
"height": 300,
"title": "Exceptions"
});
$dial.load(base_path + "getExceptionDates/", opts, function() {
$dial.find(".exception_selector_link").click(function(ev2) {
ev2.preventDefault();
var ts = $(this).data("timestamp");
var str = $(this).html();
var $part = $("<div data-timestamp='" + ts + "' class='except'><input type='hidden' class='rec_exception' name='rec_exceptions[]' value='" + ts + "'><a href='#' class='exception_remover'>[remove]</a> " + str + "</div>");
var found = false;
$(".rec_exceptions_holder .except").each(function() {
if (!found && ts < $(this).data("timestamp")) {
found = true;
$part.insertBefore(this);
}
});
if (!found) $(".rec_exceptions_holder").append($part);
$(".rec_exceptions .rec_exceptions_holder").show();
$(".rec_exceptions .rec_exceptions_none").hide();
$dial.dialog("destroy").remove();
})
});
});
}

View file

@ -5,8 +5,10 @@
(function ($) {
"use strict";
var __WDAY = new Array(i18n.xgcalendar.dateformat.sun, i18n.xgcalendar.dateformat.mon, i18n.xgcalendar.dateformat.tue, i18n.xgcalendar.dateformat.wed, i18n.xgcalendar.dateformat.thu, i18n.xgcalendar.dateformat.fri, i18n.xgcalendar.dateformat.sat);
var __MonthName = new Array(i18n.xgcalendar.dateformat.jan, i18n.xgcalendar.dateformat.feb, i18n.xgcalendar.dateformat.mar, i18n.xgcalendar.dateformat.apr, i18n.xgcalendar.dateformat.may, i18n.xgcalendar.dateformat.jun, i18n.xgcalendar.dateformat.jul, i18n.xgcalendar.dateformat.aug, i18n.xgcalendar.dateformat.sep, i18n.xgcalendar.dateformat.oct, i18n.xgcalendar.dateformat.nov, i18n.xgcalendar.dateformat.dec);
var __WDAY = $.datepicker._defaults.dayNamesShort;
//new Array(i18n.xgcalendar.dateformat.sun, i18n.xgcalendar.dateformat.mon, i18n.xgcalendar.dateformat.tue, i18n.xgcalendar.dateformat.wed, i18n.xgcalendar.dateformat.thu, i18n.xgcalendar.dateformat.fri, i18n.xgcalendar.dateformat.sat);
var __MonthName = $.datepicker._defaults.monthNamesShort;
//new Array(i18n.xgcalendar.dateformat.jan, i18n.xgcalendar.dateformat.feb, i18n.xgcalendar.dateformat.mar, i18n.xgcalendar.dateformat.apr, i18n.xgcalendar.dateformat.may, i18n.xgcalendar.dateformat.jun, i18n.xgcalendar.dateformat.jul, i18n.xgcalendar.dateformat.aug, i18n.xgcalendar.dateformat.sep, i18n.xgcalendar.dateformat.oct, i18n.xgcalendar.dateformat.nov, i18n.xgcalendar.dateformat.dec);
function dateFormat(format) {
@ -769,8 +771,8 @@
for (i = 0; i < l; i++) {
var $col = $container.find(".tgCol" + i);
for (var j = 0; j < events[i].length; j++) {
if (events[i][j].event["color"] && events[i][j].event["color"].match(/^#[0-9a-f]{6}$/i)) {
c = events[i][j].event["color"];
if (events[i][j].event["color"] && events[i][j].event["color"].match(/^[0-9a-f]{6}$/i)) {
c = "#" + events[i][j].event["color"];
}
else {
c = option.std_color;
@ -787,7 +789,7 @@
function getTitle(event) {
var timeshow, eventshow;
var showtime = event["is_allday"] != 1;
eventshow = event["subject"];
eventshow = event["summary"];
var startformat = getymformat(event["start"], null, showtime, true);
var endformat = getymformat(event["end"], event["start"], showtime, true);
timeshow = dateFormat.call(event["start"], startformat) + " - " + dateFormat.call(event["end"], endformat);
@ -819,7 +821,7 @@
var p = { bdcolor:theme[0], bgcolor2:theme[0], bgcolor1:theme[2], width:"70%", icon:"", title:"", data:"" };
p.starttime = pZero(e.st.hour) + ":" + pZero(e.st.minute);
p.endtime = pZero(e.et.hour) + ":" + pZero(e.et.minute);
p.content = e.event["subject"];
p.content = e.event["summary"];
p.title = getTitle(e.event);
var icons = [];
if (e.event["has_notification"] == 1) icons.push("<I class=\"cic cic-tmr\">&nbsp;</I>");
@ -1146,12 +1148,12 @@
var p = { color:theme[2], title:"", extendClass:"", extendHTML:"", data:"" };
p.title = getTitle(e.event);
p.id = "bbit_cal_event_" + e.event["uri"];
p.id = "bbit_cal_event_" + e.event["jq_id"];
if (option.enableDrag && e.event["is_editable_quick"] == 1) {
p.eclass = "drag";
}
else {
p.eclass = "cal_" + e.event["uri"];
p.eclass = "cal_" + e.event["jq_id"];
}
p.eclass += " " + (e.event["is_editable"] ? "editable" : "not_editable");
var sp = "<span style=\"cursor: pointer\">{content}</span>";
@ -1175,10 +1177,10 @@
}
var cen;
if (!e.allday && !sf) {
cen = pZero(e.st.hour) + ":" + pZero(e.st.minute) + " " + e.event["subject"];
cen = pZero(e.st.hour) + ":" + pZero(e.st.minute) + " " + e.event["summary"];
}
else {
cen = e.event["subject"];
cen = e.event["summary"];
}
var content = [];
if (cen.indexOf("Geburtstag:") == 0) {
@ -1294,7 +1296,7 @@
}
if (option.eventItems[i]["start"] >= es) {
for (var j = 0; j < jl; j++) {
if (option.eventItems[i]["uri"] == events[j]["uri"] && option.eventItems[i]["start"] < start) {
if (option.eventItems[i]["jq_id"] == events[j]["jq_id"] && option.eventItems[i]["start"] < start) {
events.splice(j, 1); //for duplicated event
jl--;
break;
@ -1477,7 +1479,7 @@
$("#bbit-cs-buddle").css("visibility", "hidden");
var calid = $("#bbit-cs-id").val();
var param = [
{ "name":"calendarId", value:calid },
{ "name":"jq_id", value:calid },
{ "name":"type", value:type}
];
var de = rebyKey(calid, true);
@ -1609,8 +1611,8 @@
var location = "";
if (data["location"] != "") location = data["location"] + ", ";
$("#bbit-cs-buddle-timeshow").html(location + ss.join(""));
$bud.find(".bbit-cs-what").html(data["subject"]).attr("href", data["url_detail"]);
$("#bbit-cs-id").val(data["uri"]);
$bud.find(".bbit-cs-what").html(data["summary"]).attr("href", data["url_detail"]);
$("#bbit-cs-id").val(data["jq_id"]);
$bud.data("cdata", data);
$bud.css({ "visibility":"visible", left:pos.left, top:pos.top });
@ -1684,11 +1686,11 @@
return false;
}
option.isloading = true;
var id = data["uri"];
var id = data["jq_id"];
var os = data["start"];
var od = data["end"];
var param = [
{ "name":"calendarId", value:id },
{ "name":"jq_id", value:id },
{ "name":"CalendarStartTime", value:Math.floor(start.getTime() / 1000) },
{ "name":"CalendarEndTime", value:Math.floor(end.getTime() / 1000) }
];
@ -1744,7 +1746,7 @@
temparr.push('<table class="cb-table"><tbody><tr><th class="cb-key">');
temparr.push(i18n.xgcalendar.time, ':</th><td class=cb-value><div id="bbit-cal-buddle-timeshow"></div></td></tr><tr><th class="cb-key">');
temparr.push(i18n.xgcalendar.content, ':</th><td class="cb-value"><div class="textbox-fill-wrapper"><div class="textbox-fill-mid"><input id="bbit-cal-what" class="textbox-fill-input"/></div></div><div class="cb-example">');
temparr.push(i18n.xgcalendar.example, '</div></td></tr></tbody></table><input id="bbit-cal-start" type="hidden"/><input id="bbit-cal-end" type="hidden"/><input id="bbit-cal-allday" type="hidden"/><input id="bbit-cal-quickAddBTN" value="');
temparr.push(i18n.xgcalendar.example, '</div></td></tr></tbody></table><input id="bbit-cal-start" type="hidden"/><input id="bbit-cal-end" type="hidden"/><input id="bbit-cal-allday" type="hidden"/><input value="');
temparr.push(i18n.xgcalendar.create_event, '" type="submit"/>&nbsp; <a href="" class="lk bbit-cal-editLink">');
temparr.push(i18n.xgcalendar.update_detail, ' <StrONG>&gt;&gt;</StrONG></SPAN></div></div></div><tr><td><div id="bl1" class="bubble-corner"><div class="bubble-sprite bubble-bl"></div></div><td><div class="bubble-bottom"></div><td><div id="br1" class="bubble-corner"><div class="bubble-sprite bubble-br"></div></div></tr></tbody></table><div id="bubbleClose1" class="bubble-closebutton"></div><div id="prong2" class="prong"><div class=bubble-sprite></div></div></div>');
temparr.push('</form>');
@ -1789,7 +1791,6 @@
param[param.length] = option.extParam[pi];
}
}
if (option.quickAddHandler && $.isFunction(option.quickAddHandler)) {
option.quickAddHandler.call(this, param);
$("#bbit-cal-buddle").css("visibility", "hidden");
@ -1804,8 +1805,9 @@
ed = new Date(dateend),
diff = DateDiff("d", sd, ed);
var newdata = {
"uri":"",
"subject":what,
"jq_id":"",
"ev_id":"",
"summary":what,
"start":sd,
"end":ed,
"is_allday":(allday == "1" ? 1 : 0),
@ -1886,7 +1888,7 @@
var sl = option.eventItems.length;
var i = -1;
for (var j = 0; j < sl; j++) {
if (option.eventItems[j]["uri"] == key) {
if (option.eventItems[j]["jq_id"] == key) {
i = j;
break;
}
@ -2352,7 +2354,7 @@
d.target.hide();
ny = gP(gh.sh, gh.sm);
d.top = ny;
tempdata = buildtempdayevent(gh.sh, gh.sm, gh.eh, gh.em, gh.h, data["subject"], false, false, data["color"]);
tempdata = buildtempdayevent(gh.sh, gh.sm, gh.eh, gh.em, gh.h, data["summary"], false, false, data["color"]);
cpwrap = $("<div class='ca-evpi drag-chip-wrapper' style='top:" + ny + "px'/>").html(tempdata);
evid = ".tgOver" + d.target.parent().data("col");
$gridcontainer.find(evid).append(cpwrap);
@ -2389,7 +2391,7 @@
//log.info("ny=" + ny);
gh = gW(ny, ny + d.h);
//log.info("sh=" + gh.sh + ",sm=" + gh.sm);
tempdata = buildtempdayevent(gh.sh, gh.sm, gh.eh, gh.em, gh.h, data["subject"], false, false, data["color"]);
tempdata = buildtempdayevent(gh.sh, gh.sm, gh.eh, gh.em, gh.h, data["summary"], false, false, data["color"]);
d.cpwrap.css("top", ny + "px").html(tempdata);
}
d.ny = ny;
@ -2415,7 +2417,7 @@
d.target.hide();
ny = gP(gh.sh, gh.sm);
d.top = ny;
tempdata = buildtempdayevent(gh.sh, gh.sm, gh.eh, gh.em, gh.h, data["subject"], "100%", true, data["color"]);
tempdata = buildtempdayevent(gh.sh, gh.sm, gh.eh, gh.em, gh.h, data["summary"], "100%", true, data["color"]);
cpwrap = $("<div class='ca-evpi drag-chip-wrapper' style='top:" + ny + "px'/>").html(tempdata);
evid = ".tgOver" + d.target.parent().data("col");
$gridcontainer.find(evid).append(cpwrap);
@ -2427,7 +2429,7 @@
nh = pnh > 1 ? nh - pnh + Math.ceil(option.hour_height / 2) : nh - pnh;
if (d.nh != nh) {
gh = gW(d.top, d.top + nh);
tempdata = buildtempdayevent(gh.sh, gh.sm, gh.eh, gh.em, gh.h, data["subject"], "100%", true, data["color"]);
tempdata = buildtempdayevent(gh.sh, gh.sm, gh.eh, gh.em, gh.h, data["summary"], "100%", true, data["color"]);
d.cpwrap.html(tempdata);
}
d.nh = nh;

View file

@ -7,26 +7,7 @@ var i18n = $.extend({}, i18n || {}, {
"year_index": 2,
"month_index": 1,
"day_index": 0,
"day": "d",
"sun": "So",
"mon": "Mo",
"tue": "Di",
"wed": "Mi",
"thu": "Do",
"fri": "Fr",
"sat": "Sa",
"jan": "Jan",
"feb": "Feb",
"mar": "Mär",
"apr": "Apr",
"may": "Mai",
"jun": "Jun",
"jul": "Jul",
"aug": "Aug",
"sep": "Sep",
"oct": "Okt",
"nov": "Nov",
"dec": "Dez"
"day": "d"
},
"no_implemented": "Nicht eingebaut",
"to_date_view": "Zum aktuellen Datum gehen",

View file

@ -7,26 +7,7 @@ var i18n = $.extend({}, i18n || {}, {
"year_index": 2,
"month_index": 1,
"day_index": 0,
"day": "d",
"sun": "Su",
"mon": "Mo",
"tue": "Tu",
"wed": "Mi",
"thu": "Th",
"fri": "Fr",
"sat": "Sa",
"jan": "Jan",
"feb": "Feb",
"mar": "Mar",
"apr": "Apr",
"may": "May",
"jun": "Jun",
"jul": "Jul",
"aug": "Aug",
"sep": "Sep",
"oct": "Oct",
"nov": "Nov",
"dec": "Dec"
"day": "d"
},
"no_implemented": "Not implemented",
"to_date_view": "Go to today",

View file

@ -0,0 +1,238 @@
<?php
/**
* @param mixed $obj
* @return string
*/
function wdcal_jsonp_encode($obj)
{
$str = json_encode($obj);
if (isset($_REQUEST["callback"])) {
$str = $_REQUEST["callback"] . "(" . $str . ")";
}
return $str;
}
/**
* @param string $day
* @param int $weekstartday
* @param int $num_days
* @param string $type
* @return array
*/
function wdcal_get_list_range_params($day, $weekstartday, $num_days, $type)
{
$phpTime = IntVal($day);
switch ($type) {
case "month":
$st = mktime(0, 0, 0, date("m", $phpTime), 1, date("Y", $phpTime));
$et = mktime(0, 0, -1, date("m", $phpTime) + 1, 1, date("Y", $phpTime));
break;
case "week":
//suppose first day of a week is monday
$monday = date("d", $phpTime) - date('N', $phpTime) + 1;
//echo date('N', $phpTime);
$st = mktime(0, 0, 0, date("m", $phpTime), $monday, date("Y", $phpTime));
$et = mktime(0, 0, -1, date("m", $phpTime), $monday + 7, date("Y", $phpTime));
break;
case "multi_days":
//suppose first day of a week is monday
$monday = date("d", $phpTime) - date('N', $phpTime) + $weekstartday;
//echo date('N', $phpTime);
$st = mktime(0, 0, 0, date("m", $phpTime), $monday, date("Y", $phpTime));
$et = mktime(0, 0, -1, date("m", $phpTime), $monday + $num_days, date("Y", $phpTime));
break;
case "day":
$st = mktime(0, 0, 0, date("m", $phpTime), date("d", $phpTime), date("Y", $phpTime));
$et = mktime(0, 0, -1, date("m", $phpTime), date("d", $phpTime) + 1, date("Y", $phpTime));
break;
default:
return array(0, 0);
}
return array($st, $et);
}
/**
* @param Sabre_DAV_Server $server
* @param string $right
* @return null|Sabre_CalDAV_Calendar
*/
function wdcal_print_feed_getCal(&$server, $right)
{
$cals = dav_get_current_user_calendars($server, $right);
$calfound = null;
for ($i = 0; $i < count($cals) && $calfound === null; $i++) {
$prop = $cals[$i]->getProperties(array("id"));
if (isset($prop["id"]) && (!isset($_REQUEST["cal"]) || in_array($prop["id"], $_REQUEST["cal"]))) $calfound = $cals[$i];
}
return $calfound;
}
/**
*
*/
function wdcal_print_feed($base_path = "")
{
$server = dav_create_server(true, true, false);
$ret = null;
$method = $_GET["method"];
switch ($method) {
case "add":
$cs = wdcal_print_feed_getCal($server, DAV_ACL_WRITE);
if ($cs == null) {
echo wdcal_jsonp_encode(array('IsSuccess' => false,
'Msg' => t('No access')));
killme();
}
try {
$item = dav_create_empty_vevent();
$component = dav_get_eventComponent($item);
$component->add("SUMMARY", icalendar_sanitize_string(dav_compat_parse_text_serverside("CalendarTitle")));
if (isset($_REQUEST["allday"])) $type = Sabre_VObject_Property_DateTime::DATE;
else $type = Sabre_VObject_Property_DateTime::LOCALTZ;
$datetime_start = new Sabre_VObject_Property_DateTime("DTSTART");
$datetime_start->setDateTime(new DateTime(date("Y-m-d H:i:s", IntVal($_REQUEST["CalendarStartTime"]))), $type);
$datetime_end = new Sabre_VObject_Property_DateTime("DTEND");
$datetime_end->setDateTime(new DateTime(date("Y-m-d H:i:s", IntVal($_REQUEST["CalendarEndTime"]))), $type);
$component->add($datetime_start);
$component->add($datetime_end);
$uid = $component->__get("UID");
$data = $item->serialize();
$cs->createFile($uid . ".ics", $data);
$ret = array(
'IsSuccess' => true,
'Msg' => 'add success',
'Data' => $uid . ".ics",
);
} catch (Exception $e) {
$ret = array(
'IsSuccess' => false,
'Msg' => $e->__toString(),
);
}
break;
case "list":
$weekstartday = (isset($_REQUEST["weekstartday"]) ? IntVal($_REQUEST["weekstartday"]) : 1); // 1 = Monday
$num_days = (isset($_REQUEST["num_days"]) ? IntVal($_REQUEST["num_days"]) : 7);
$ret = null;
$date = wdcal_get_list_range_params($_REQUEST["showdate"], $weekstartday, $num_days, $_REQUEST["viewtype"]);
$ret = array();
$ret['events'] = array();
$ret["issort"] = true;
$ret["start"] = $date[0];
$ret["end"] = $date[1];
$ret['error'] = null;
$cals = dav_get_current_user_calendars($server, DAV_ACL_READ);
foreach ($cals as $cal) {
$prop = $cal->getProperties(array("id"));
if (isset($prop["id"]) && (!isset($_REQUEST["cal"]) || in_array($prop["id"], $_REQUEST["cal"]))) {
$backend = wdcal_calendar_factory_by_id($prop["id"]);
$events = $backend->listItemsByRange($prop["id"], $date[0], $date[1], $base_path);
$ret["events"] = array_merge($ret["events"], $events);
}
}
$tmpev = array();
foreach ($ret["events"] as $e) {
if (!isset($tmpev[$e["start"]])) $tmpev[$e["start"]] = array();
$tmpev[$e["start"]][] = $e;
}
ksort($tmpev);
$ret["events"] = array();
foreach ($tmpev as $e) foreach ($e as $f) $ret["events"][] = $f;
break;
case "update":
$r = q("SELECT `calendarobject_id`, `calendar_id` FROM %s%sjqcalendar WHERE `id`=%d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($_REQUEST["jq_id"]));
if (count($r) != 1) {
echo wdcal_jsonp_encode(array('IsSuccess' => false,
'Msg' => t('No access')));
killme();
}
try {
$cs = dav_get_current_user_calendar_by_id($server, $r[0]["calendar_id"], DAV_ACL_READ);
$obj_uri = Sabre_CalDAV_Backend_Common::loadCalendarobjectById($r[0]["calendarobject_id"]);
$vObject = dav_get_current_user_calendarobject($server, $cs, $obj_uri["uri"], DAV_ACL_WRITE);
$component = dav_get_eventComponent($vObject);
if (!$component) {
echo wdcal_jsonp_encode(array('IsSuccess' => false,
'Msg' => t('No access')));
killme();
}
if (isset($_REQUEST["allday"])) $type = Sabre_VObject_Property_DateTime::DATE;
else $type = Sabre_VObject_Property_DateTime::LOCALTZ;
$datetime_start = new Sabre_VObject_Property_DateTime("DTSTART");
$datetime_start->setDateTime(new DateTime(date("Y-m-d H:i:s", IntVal($_REQUEST["CalendarStartTime"]))), $type);
$datetime_end = new Sabre_VObject_Property_DateTime("DTEND");
$datetime_end->setDateTime(new DateTime(date("Y-m-d H:i:s", IntVal($_REQUEST["CalendarEndTime"]))), $type);
$component->__unset("DTSTART");
$component->__unset("DTEND");
$component->add($datetime_start);
$component->add($datetime_end);
$data = $vObject->serialize();
/** @var Sabre_CalDAV_CalendarObject $child */
$child = $cs->getChild($obj_uri["uri"]);
$child->put($data);
$ret = array(
'IsSuccess' => true,
'Msg' => 'Succefully',
);
} catch (Exception $e) {
echo wdcal_jsonp_encode(array('IsSuccess' => false,
'Msg' => t('No access')));
killme();
}
break;
case "remove":
$r = q("SELECT `calendarobject_id`, `calendar_id` FROM %s%sjqcalendar WHERE `id`=%d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($_REQUEST["jq_id"]));
if (count($r) != 1) {
echo wdcal_jsonp_encode(array('IsSuccess' => false,
'Msg' => t('No access')));
killme();
}
try {
$cs = dav_get_current_user_calendar_by_id($server, $r[0]["calendar_id"], DAV_ACL_WRITE);
$obj_uri = Sabre_CalDAV_Backend_Common::loadCalendarobjectById($r[0]["calendarobject_id"]);
$child = $cs->getChild($obj_uri["uri"]);
$child->delete();
$ret = array(
'IsSuccess' => true,
'Msg' => 'Succefully',
);
} catch (Exception $e) {
echo wdcal_jsonp_encode(array('IsSuccess' => false,
'Msg' => t('No access')));
killme();
}
break;
}
echo wdcal_jsonp_encode($ret);
killme();
}

View file

@ -40,6 +40,13 @@ abstract class wdcal_local
return $format;
}
/**
* @static
* @abstract
* @return string
*/
abstract static function getLanguageCode();
/**
* @abstract
* @static
@ -77,6 +84,13 @@ abstract class wdcal_local
*/
abstract function date_timestamp2local($ts);
/**
* @abstract
* @param int $ts
* @return string
*/
abstract function date_timestamp2localDate($ts);
/**
* @abstract
* @return int
@ -119,6 +133,14 @@ abstract class wdcal_local
class wdcal_local_us extends wdcal_local {
/**
* @static
* @return string
*/
static function getLanguageCode() {
return "en";
}
/**
* @return string
*/
@ -152,6 +174,14 @@ class wdcal_local_us extends wdcal_local {
return date("m/d/Y H:i", $ts);
}
/**
* @param int $ts
* @return string
*/
function date_timestamp2localDate($ts) {
return date("l, F jS Y", $ts);
}
/**
* @return int
*/
@ -198,6 +228,14 @@ class wdcal_local_us extends wdcal_local {
class wdcal_local_de extends wdcal_local {
/**
* @static
* @return string
*/
static function getLanguageCode() {
return "de";
}
/**
* @return string
*/
@ -231,6 +269,14 @@ class wdcal_local_de extends wdcal_local {
return date("d.m.Y H:i", $ts);
}
/**
* @param int $ts
* @return string
*/
function date_timestamp2localDate($ts) {
return date("l, j. F Y", $ts);
}
/**
* @return int
*/

View file

@ -0,0 +1,510 @@
<?php
/**
* @param wdcal_local $localization
* @param string $baseurl
* @param int $uid
* @param int $calendar_id
* @param int $uri
* @param string $recurr_uri
* @return string
*/
function wdcal_getEditPage_str(&$localization, $baseurl, $uid, $calendar_id, $uri, $recurr_uri = "")
{
$server = dav_create_server(true, true, false);
if ($uri > 0) {
$calendar = dav_get_current_user_calendar_by_id($server, $calendar_id, DAV_ACL_WRITE);
if (!$calendar) {
$calendar = dav_get_current_user_calendar_by_id($server, $calendar_id, DAV_ACL_READ);
$calendars = array();
} else {
$calendars = dav_get_current_user_calendars($server, DAV_ACL_WRITE);
}
if ($calendar == null) return "Calendar not found";
$obj_uri = Sabre_CalDAV_Backend_Common::loadCalendarobjectById($uri);
$vObject = dav_get_current_user_calendarobject($server, $calendar, $obj_uri["uri"], DAV_ACL_WRITE);
$component = dav_get_eventComponent($vObject);
if ($component == null) return t('Could not open component for editing');
/** @var Sabre_VObject_Property_DateTime $dtstart */
$dtstart = $component->__get("DTSTART");
$event = array(
"id" => IntVal($uri),
"Summary" => ($component->__get("SUMMARY") ? $component->__get("SUMMARY")->value : null),
"StartTime" => $dtstart->getDateTime()->getTimeStamp(),
"EndTime" => Sabre_CalDAV_Backend_Common::getDtEndTimeStamp($component),
"IsAllDayEvent" => (strlen($dtstart->value) == 8),
"Description" => ($component->__get("DESCRIPTION") ? $component->__get("DESCRIPTION")->value : null),
"Location" => ($component->__get("LOCATION") ? $component->__get("LOCATION")->value : null),
"Color" => ($component->__get("X-ANIMEXX-COLOR") ? $component->__get("X-ANIMEXX-COLOR")->value : null),
);
$exdates = $component->select("EXDATE");
$recurrentce_exdates = array();
/** @var Sabre_VObject_Property_MultiDateTime $x */
foreach ($exdates as $x) {
/** @var DateTime $y */
$z = $x->getDateTimes();
foreach ($z as $y) $recurrentce_exdates[] = $y->getTimeStamp();
}
if ($component->select("RRULE")) $recurrence = new Sabre_VObject_RecurrenceIterator($vObject, (string)$component->__get("UID"));
else $recurrence = null;
} elseif (isset($_REQUEST["start"]) && $_REQUEST["start"] > 0) {
$calendars = dav_get_current_user_calendars($server, DAV_ACL_WRITE);
$calendar = dav_get_current_user_calendar_by_id($server, $calendar_id, DAV_ACL_WRITE);
$event = array(
"id" => 0,
"Summary" => $_REQUEST["title"],
"StartTime" => InTVal($_REQUEST["start"]),
"EndTime" => IntVal($_REQUEST["end"]),
"IsAllDayEvent" => $_REQUEST["isallday"],
"Description" => "",
"Location" => "",
"Color" => "#5858ff",
);
if ($_REQUEST["isallday"]) {
$notifications = array(array("rel" => "start", "type" => "duration", "period" => "hour", "period_val" => 24));
} else {
$notifications = array(array("rel" => "start", "type" => "duration", "period" => "hour", "period_val" => 1));
}
$recurrence = null;
$recurrentce_exdates = array();
} else {
$calendars = dav_get_current_user_calendars($server, DAV_ACL_WRITE);
$calendar = dav_get_current_user_calendar_by_id($server, $calendar_id, DAV_ACL_WRITE);
$event = array(
"id" => 0,
"Summary" => "",
"StartTime" => time(),
"EndTime" => time() + 3600,
"IsAllDayEvent" => "0",
"Description" => "",
"Location" => "",
"Color" => "#5858ff",
);
$notifications = array(array("rel" => "start", "type" => "duration", "period" => "hour", "period_val" => 1));
$recurrence = null;
$recurrentce_exdates = array();
}
$postto = $baseurl . "/dav/wdcal/" . ($uri == 0 ? "new/" : $calendar_id . "/" . $uri . "/edit/");
$out = "<a href='" . $baseurl . "/dav/wdcal/'>" . t("Go back to the calendar") . "</a><br><br>";
$out .= "<form method='POST' action='$postto'>
<input type='hidden' name='form_security_token' value='" . get_form_security_token('caledit') . "'>\n";
$out .= "<h2>" .t("Event data") . "</h2>";
$out .= "<label for='calendar'>" . t("Calendar") . ":</label><select name='calendar' size='1'>";
foreach ($calendars as $cal) {
$prop = $cal->getProperties(array("id", DAV_DISPLAYNAME));
$out .= "<option value='" . $prop["id"] . "' ";
if ($prop["id"] == $calendar_id) $out .= "selected";
$out .= ">" . escape_tags($prop[DAV_DISPLAYNAME]) . "</option>\n";
}
$out .= "</select><br>\n";
$out .= "<label class='block' for='cal_summary'>" . t("Subject") . ":</label>
<input name='color' id='cal_color' value='" . (strlen($event["Color"]) != 7 ? "#5858ff" : escape_tags($event["Color"])) . "'>
<input name='summary' id='cal_summary' value='" . escape_tags($event["Summary"]) . "'><br>\n";
$out .= "<label class='block' for='cal_allday'>Is All-Day event:</label><input type='checkbox' name='allday' id='cal_allday' " . ($event["IsAllDayEvent"] ? "checked" : "") . "><br>\n";
$out .= "<label class='block' for='cal_startdate'>" . t("Starts") . ":</label>";
$out .= "<input name='start_date' value='" . $localization->dateformat_datepicker_php($event["StartTime"]) . "' id='cal_start_date'>";
$out .= "<input name='start_time' value='" . date("H:i", $event["StartTime"]) . "' id='cal_start_time'>";
$out .= "<br>\n";
$out .= "<label class='block' for='cal_enddate'>" . t("Ends") . ":</label>";
$out .= "<input name='end_date' value='" . $localization->dateformat_datepicker_php($event["EndTime"]) . "' id='cal_end_date'>";
$out .= "<input name='end_time' value='" . date("H:i", $event["EndTime"]) . "' id='cal_end_time'>";
$out .= "<br>\n";
$out .= "<label class='block' for='cal_location'>" . t("Location") . ":</label><input name='location' id='cal_location' value='" . escape_tags($event["Location"]) . "'><br>\n";
$out .= "<label class='block' for='event-desc-textarea'>" . t("Description") . ":</label> <textarea id='event-desc-textarea' name='wdcal_desc' style='vertical-align: top; width: 400px; height: 100px;'>" . escape_tags($event["Description"]) . "</textarea>";
$out .= "<br style='clear: both;'>";
$out .= "<h2>" .t("Recurrence") . "</h2>";
$out .= "<label class='block' for='rec_frequency'>" . t("Frequency") . ":</label> <select id='rec_frequency' name='rec_frequency' size='1'>";
$out .= "<option value=''>" . t("None") . "</option>\n";
$out .= "<option value='daily' "; if ($recurrence && $recurrence->frequency == "daily") $out .= "selected"; $out .= ">" . t("Daily") . "</option>\n";
$out .= "<option value='weekly' "; if ($recurrence && $recurrence->frequency == "weekly") $out .= "selected"; $out .= ">" . t("Weekly") . "</option>\n";
$out .= "<option value='monthly' "; if ($recurrence && $recurrence->frequency == "monthly") $out .= "selected"; $out .= ">" . t("Monthly") . "</option>\n";
$out .= "<option value='yearly' "; if ($recurrence && $recurrence->frequency == "yearly") $out .= "selected"; $out .= ">" . t("Yearly") . "</option>\n";
$out .="</select><br>\n";
$out .= "<div id='rec_details'>";
$select = "<select id='rec_interval' name='rec_interval' size='1'>";
for ($i = 1; $i < 50; $i++) {
$select .= "<option value='$i' ";
if ($recurrence && $i == $recurrence->interval) $select .= "selected";
$select .= ">$i</option>\n";
}
$select .= "</select>";
$time = "<span class='rec_daily'>" . t("days") . "</span>";
$time .= "<span class='rec_weekly'>" . t("weeks") . "</span>";
$time .= "<span class='rec_monthly'>" . t("months") . "</span>";
$time .= "<span class='rec_yearly'>" . t("years") . "</span>";
$out .= "<label class='block' for='rev_interval'>" . t("Interval") . ":</label> " . str_replace(array("%select%", "%time%"), array($select, $time), t("All %select% %time%")) . "<br>";
$out .= "<div class='rec_daily'>";
$out .= "<label class='block'>" . t("Days") . ":</label>";
if ($recurrence && $recurrence->byDay) {
$byday = $recurrence->byDay;
} else {
$byday = array("MO", "TU", "WE", "TH", "FR", "SA", "SU");
}
if ($localization->getFirstDayOfWeek() == 0) {
$out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='SU' "; if (in_array("SU", $byday)) $out .= "checked"; $out .= ">" . t("Sunday") . "</label> &nbsp; ";
}
$out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='MO' "; if (in_array("MO", $byday)) $out .= "checked"; $out .= ">" . t("Monday") . "</label> &nbsp; ";
$out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='TU' "; if (in_array("TU", $byday)) $out .= "checked"; $out .= ">" . t("Tuesday") . "</label> &nbsp; ";
$out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='WE' "; if (in_array("WE", $byday)) $out .= "checked"; $out .= ">" . t("Wednesday") . "</label> &nbsp; ";
$out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='TH' "; if (in_array("TH", $byday)) $out .= "checked"; $out .= ">" . t("Thursday") . "</label> &nbsp; ";
$out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='FR' "; if (in_array("FR", $byday)) $out .= "checked"; $out .= ">" . t("Friday") . "</label> &nbsp; ";
$out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='SA' "; if (in_array("SA", $byday)) $out .= "checked"; $out .= ">" . t("Saturday") . "</label> &nbsp; ";
if ($localization->getFirstDayOfWeek() != 0) {
$out .= "<label class='plain'><input class='rec_daily_byday' type='checkbox' name='rec_daily_byday[]' value='SU' "; if (in_array("SU", $byday)) $out .= "checked"; $out .= ">" . t("Sunday") . "</label> &nbsp; ";
}
$out .= "</div>";
$out .= "<div class='rec_weekly'>";
$out .= "<label class='block'>" . t("Days") . ":</label>";
if ($recurrence && $recurrence->byDay) {
$byday = $recurrence->byDay;
} else {
$byday = array("MO", "TU", "WE", "TH", "FR", "SA", "SU");
}
if ($localization->getFirstDayOfWeek() == 0) {
$out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='SU' "; if (in_array("SU", $byday)) $out .= "checked"; $out .= ">" . t("Sunday") . "</label> &nbsp; ";
}
$out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='MO' "; if (in_array("MO", $byday)) $out .= "checked"; $out .= ">" . t("Monday") . "</label> &nbsp; ";
$out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='TU' "; if (in_array("TU", $byday)) $out .= "checked"; $out .= ">" . t("Tuesday") . "</label> &nbsp; ";
$out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='WE' "; if (in_array("WE", $byday)) $out .= "checked"; $out .= ">" . t("Wednesday") . "</label> &nbsp; ";
$out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='TH' "; if (in_array("TH", $byday)) $out .= "checked"; $out .= ">" . t("Thursday") . "</label> &nbsp; ";
$out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='FR' "; if (in_array("FR", $byday)) $out .= "checked"; $out .= ">" . t("Friday") . "</label> &nbsp; ";
$out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='SA' "; if (in_array("SA", $byday)) $out .= "checked"; $out .= ">" . t("Saturday") . "</label> &nbsp; ";
if ($localization->getFirstDayOfWeek() != 0) {
$out .= "<label class='plain'><input class='rec_weekly_byday' type='checkbox' name='rec_weekly_byday[]' value='SU' "; if (in_array("SU", $byday)) $out .= "checked"; $out .= ">" . t("Sunday") . "</label> &nbsp; ";
}
$out .= "<br>";
$out .= "<label class='block'>" . t("First day of week:") . "</label>";
if ($recurrence && $recurrence->weekStart != "") $wkst = $recurrence->weekStart;
else {
if ($localization->getFirstDayOfWeek() == 0) $wkst = "SU";
else $wkst = "MO";
}
$out .= "<label class='plain'><input type='radio' name='rec_weekly_wkst' value='SU' "; if ($wkst == "SU") $out .= "checked"; $out .= ">" . t("Sunday") . "</label> &nbsp; ";
$out .= "<label class='plain'><input type='radio' name='rec_weekly_wkst' value='MO' "; if ($wkst == "MO") $out .= "checked"; $out .= ">" . t("Monday") . "</label><br>\n";
$out .= "</div>";
$monthly_rule = "bymonthday"; // @TODO
$out .= "<div class='rec_monthly'>";
$out .= "<label class='block' name='rec_monthly_day'>" . t("Day of month") . ":</label>";
$out .= "<select id='rec_monthly_day' name='rec_monthly_day' size='1'>";
$out .= "<option value='bymonthday' "; if ($monthly_rule == "bymonthday") $out .= "selected"; $out .= ">" . t("#num#th of each month") . "</option>\n";
$out .= "<option value='bymonthday_neg' "; if ($monthly_rule == "bymonthday_neg") $out .= "selected"; $out .= ">" . t("#num#th-last of each month") . "</option>\n";
$out .= "<option value='byday' "; if ($monthly_rule == "byday") $out .= "selected"; $out .= ">" . t("#num#th #wkday# of each month") . "</option>\n";
$out .= "<option value='byday_neg' "; if ($monthly_rule == "byday_neg") $out .= "selected"; $out .= ">" . t("#num#th-last #wkday# of each month") . "</option>\n";
$out .= "</select>";
$out .= "</div>\n";
$out .= "<div class='rec_yearly'>";
$out .= "<label class='block' name='rec_yearly_day'>" . t("Month") . ":</label> <span class='rec_month_name'>#month#</span><br>\n";
$out .= "<label class='block' name='rec_yearly_day'>" . t("Day of month") . ":</label>";
$out .= "<select id='rec_yearly_day' name='rec_yearly_day' size='1'>";
$out .= "<option value='bymonthday' "; if ($monthly_rule == "bymonthday") $out .= "selected"; $out .= ">" . t("#num#th of each month") . "</option>\n";
$out .= "<option value='bymonthday_neg' "; if ($monthly_rule == "bymonthday_neg") $out .= "selected"; $out .= ">" . t("#num#th-last of each month") . "</option>\n";
$out .= "<option value='byday' "; if ($monthly_rule == "byday") $out .= "selected"; $out .= ">" . t("#num#th #wkday# of each month") . "</option>\n";
$out .= "<option value='byday_neg' "; if ($monthly_rule == "byday_neg") $out .= "selected"; $out .= ">" . t("#num#th-last #wkday# of each month") . "</option>\n";
$out .= "</select>";
$out .= "</div>\n";
if ($recurrence) {
$until = $recurrence->until;
$count = $recurrence->count;
if (is_a($until, "DateTime")) {
/** @var DateTime $until */
$rule_type = "date";
$rule_until_date = $until->getTimestamp();
$rule_until_count = 1;
} elseif ($count > 0) {
$rule_type = "count";
$rule_until_date = time();
$rule_until_count = $count;
} else {
$rule_type = "infinite";
$rule_until_date = time();
$rule_until_count = 1;
}
} else {
$rule_type = "infinite";
$rule_until_date = time();
$rule_until_count = 1;
}
$out .= "<label class='block' for='rec_until_type'>" . t("Repeat until") . ":</label> ";
$out .= "<select name='rec_until_type' id='rec_until_type' size='1'>";
$out .= "<option value='infinite' "; if ($rule_type == "infinite") $out .= "selected"; $out .= ">" . t("Infinite") . "</option>\n";
$out .= "<option value='date' "; if ($rule_type == "date") $out .= "selected"; $out .= ">" . t("Until the following date") . ":</option>\n";
$out .= "<option value='count' "; if ($rule_type == "count") $out .= "selected"; $out .= ">" . t("Number of times") . ":</option>\n";
$out .= "</select>";
$out .= "<input name='rec_until_date' value='" . $localization->dateformat_datepicker_php($rule_until_date) . "' id='rec_until_date'>";
$out .= "<input name='rec_until_count' value='$rule_until_count' id='rec_until_count'><br>";
$out .= "<label class='block'>" . t("Exceptions") . ":</label><div class='rec_exceptions'>";
$out .= "<div class='rec_exceptions_none' ";
if (count($recurrentce_exdates) > 0) $out .= "style='display: none;'";
$out .= ">" . t("none") . "</div>";
$out .= "<div class='rec_exceptions_holder' ";
if (count($recurrentce_exdates) == 0) $out .= "style='display: none;'";
$out .= ">";
foreach ($recurrentce_exdates as $exdate) {
$out .= "<div data-timestamp='$exdate' class='except'><input type='hidden' class='rec_exception' name='rec_exceptions[]' value='$exdate'>";
$out .= "<a href='#' class='exception_remover'>[remove]</a> ";
$out .= $localization->date_timestamp2localDate($exdate);
$out .= "</div>\n";
}
$out .= "</div><div><a href='#' class='exception_adder'>[add]</a></div>";
$out .= "</div>\n";
$out .= "<br>\n";
$out .= "</div><br>";
$out .= "<h2>" .t("Notification") . "</h2>";
/*
$out .= '<input type="checkbox" name="notification" id="notification" ';
if ($notification) $out .= "checked";
$out .= '> ';
$out .= '<span id="notification_detail" style="display: none;">
<input name="notification_value" value="' . $notification_value . '" size="3">
<select name="notification_type" size="1">
<option value="minute" ';
if ($notification_type == "minute") $out .= "selected";
$out .= '> ' . t('Minutes') . '</option>
<option value="hour" ';
if ($notification_type == "hour") $out .= "selected";
$out .= '> ' . t('Hours') . '</option>
<option value="day" ';
if ($notification_type == "day") echo "selected";
$out .= '> ' . t('Days') . '</option>
</select> ' . t('before') . '
</span><br><br>';
*/
$out .= "<script>\$(function() {
wdcal_edit_init('" . $localization->dateformat_datepicker_js() . "', '${baseurl}/dav/');
});</script>";
$out .= "<input type='submit' name='save' value='Save'></form>";
return $out;
}
/**
* @param Sabre_VObject_Component_VEvent $component
* @param wdcal_local $localization
*/
function wdcal_set_component_date(&$component, &$localization) {
if (isset($_REQUEST["allday"])) {
$ts_start = $localization->date_local2timestamp($_REQUEST["start_date"] . " 00:00");
$ts_end = $localization->date_local2timestamp($_REQUEST["end_date"] . " 00:00");
$type = Sabre_VObject_Property_DateTime::DATE;
} else {
$ts_start = $localization->date_local2timestamp($_REQUEST["start_date"] . " " . $_REQUEST["start_time"]);
$ts_end = $localization->date_local2timestamp($_REQUEST["end_date"] . " " . $_REQUEST["end_time"]);
$type = Sabre_VObject_Property_DateTime::LOCALTZ;
}
$datetime_start = new Sabre_VObject_Property_DateTime("DTSTART");
$datetime_start->setDateTime(new DateTime(date("Y-m-d H:i:s", $ts_start)), $type);
$datetime_end = new Sabre_VObject_Property_DateTime("DTEND");
$datetime_end->setDateTime(new DateTime(date("Y-m-d H:i:s", $ts_end)), $type);
$component->__unset("DTSTART");
$component->__unset("DTEND");
$component->add($datetime_start);
$component->add($datetime_end);
}
/**
* @param Sabre_VObject_Component_VEvent $component
* @param wdcal_local $localization
*/
function wdcal_set_component_recurrence(&$component, &$localization) {
$component->__unset("RRULE");
$component->__unset("EXRULE");
$component->__unset("EXDATE");
$component->__unset("RDATE");
$part_until = "";
switch ($_REQUEST["rec_until_type"]) {
case "date":
$date = $localization->date_local2timestamp($_REQUEST["rec_until_date"]);
$part_until = ";UNTIL=" . date("Ymd", $date);
$datetime_until = new Sabre_VObject_Property_DateTime("UNTIL");
$datetime_until->setDateTime(new DateTime(date("Y-m-d H:i:s", $date)), Sabre_VObject_Property_DateTime::DATE);
break;
case "count":
$part_until = ";COUNT=" . IntVal($_REQUEST["rec_until_count"]);
break;
}
switch ($_REQUEST["rec_frequency"]) {
case "daily":
$part_freq = "FREQ=DAILY";
if (isset($_REQUEST["rec_daily_byday"])) {
$days = array();
foreach ($_REQUEST["rec_daily_byday"] as $x) if (in_array($x, array("MO", "TU", "WE", "TH", "FR", "SA", "SU"))) $days[] = $x;
if (count($days) > 0) $part_freq .= ";BYDAY=" . implode(",", $days);
}
break;
case "weekly":
$part_freq = "FREQ=WEEKLY";
if (isset($_REQUEST["rec_weekly_wkst"]) && in_array($_REQUEST["rec_weekly_wkst"], array("MO", "SU"))) $part_freq .= ";WKST=" . $_REQUEST["rec_weekly_wkst"];
if (isset($_REQUEST["rec_weekly_byday"])) {
$days = array();
foreach ($_REQUEST["rec_weekly_byday"] as $x) if (in_array($x, array("MO", "TU", "WE", "TH", "FR", "SA", "SU"))) $days[] = $x;
if (count($days) > 0) $part_freq .= ";BYDAY=" . implode(",", $days);
}
break;
case "monthly":
$part_freq = "FREQ=MONTHLY";
break;
case "FREQ=yearly":
$part_freq = "FREQ=YEARLY";
break;
default:
$part_freq = "";
}
if ($part_freq == "") return;
if (isset($_REQUEST["rec_interval"])) $part_freq .= ";INTERVAL=" . InTVal($_REQUEST["rec_interval"]);
if (isset($_REQUEST["rec_exceptions"])) {
$arr = array();
foreach ($_REQUEST["rec_exceptions"] as $except) {
$arr[] = new DateTime(date("Y-m-d H:i:s", $except));
}
/** @var Sabre_VObject_Property_MultiDateTime $prop */
$prop = Sabre_VObject_Property::create("EXDATE");
$prop->setDateTimes($arr);
$component->add($prop);
}
$rrule = $part_freq . $part_until;
$component->add(new Sabre_VObject_Property("RRULE", $rrule));
}
/**
* @param string $uri
* @param string $recurr_uri
* @param int $uid
* @param string $timezone
* @param string $goaway_url
* @return array
*/
function wdcal_postEditPage($uri, $recurr_uri = "", $uid = 0, $timezone = "", $goaway_url = "")
{
$uid = IntVal($uid);
$localization = wdcal_local::getInstanceByUser($uid);
$server = dav_create_server(true, true, false);
if ($uri > 0) {
$calendar = dav_get_current_user_calendar_by_id($server, $_REQUEST["calendar"], DAV_ACL_READ);
$obj_uri = Sabre_CalDAV_Backend_Common::loadCalendarobjectById($uri);
$obj_uri = $obj_uri["uri"];
$vObject = dav_get_current_user_calendarobject($server, $calendar, $obj_uri, DAV_ACL_WRITE);
$component = dav_get_eventComponent($vObject);
if ($component == null) return array("ok" => false, "msg" => t('Could not open component for editing'));
} else {
$calendar = dav_get_current_user_calendar_by_id($server, $_REQUEST["calendar"], DAV_ACL_WRITE);
$vObject = dav_create_empty_vevent();
$component = dav_get_eventComponent($vObject);
$obj_uri = $component->__get("UID");
}
wdcal_set_component_date($component, $localization);
wdcal_set_component_recurrence($component, $localization);
$component->__unset("LOCATION");
$component->__unset("SUMMARY");
$component->__unset("DESCRIPTION");
$component->__unset("X-ANIMEXXCOLOR");
$component->add("SUMMARY", icalendar_sanitize_string(dav_compat_parse_text_serverside("summary")));
$component->add("LOCATION", icalendar_sanitize_string(dav_compat_parse_text_serverside("location")));
$component->add("DESCRIPTION", icalendar_sanitize_string(dav_compat_parse_text_serverside("wdcal_desc")));
$component->add("X-ANIMEXX-COLOR", $_REQUEST["color"]);
$data = $vObject->serialize();
if ($uri == 0) {
$calendar->createFile($obj_uri . ".ics", $data);
} else {
$obj = $calendar->getChild($obj_uri);
$obj->put($data);
}
return array("ok" => false, "msg" => t("Saved"));
}
/**
* @return string
*/
function wdcal_getEditPage_exception_selector() {
header("Content-type: application/json");
$a = get_app();
$localization = wdcal_local::getInstanceByUser($a->user["uid"]);
$vObject = wdcal_create_empty_vevent();
foreach($vObject->getComponents() as $component) {
if ($component->name!=='VTIMEZONE') break;
}
/** @var Sabre_VObject_Component_VEvent $component */
wdcal_set_component_date($component, $localization);
wdcal_set_component_recurrence($component, $localization);
$it = new Sabre_VObject_RecurrenceIterator($vObject, (string)$component->__get("UID"));
$max_ts = mktime(0, 0, 0, 1, 1, CALDAV_MAX_YEAR + 1);
$last_start = 0;
$o = "<ul>";
$i = 0;
while($it->valid() && $last_start < $max_ts && $i++ < 1000) {
$last_start = $it->getDtStart()->getTimestamp();
$o .= "<li><a href='#' class='exception_selector_link' data-timestamp='$last_start'>" . $localization->date_timestamp2localDate($last_start) . "</a></li>\n";
$it->next();
}
$o .= "</ul>\n";
return $o;
}