forked from friendica/deprecated-addons
moved deprecated communityhome, dav and yourls to the deprecated-addons repository
This commit is contained in:
parent
24444adef3
commit
31520f804d
675 changed files with 195144 additions and 0 deletions
376
dav/common/calendar.fnk.php
Normal file
376
dav/common/calendar.fnk.php
Normal file
|
@ -0,0 +1,376 @@
|
|||
<?php
|
||||
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
|
||||
define("DAV_ACL_READ", "{DAV:}read");
|
||||
define("DAV_ACL_WRITE", "{DAV:}write");
|
||||
define("DAV_DISPLAYNAME", "{DAV:}displayname");
|
||||
define("DAV_CALENDARCOLOR", "{http://apple.com/ns/ical/}calendar-color");
|
||||
|
||||
|
||||
class DAVVersionMismatchException extends Exception
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
class vcard_source_data_email
|
||||
{
|
||||
public $email, $type;
|
||||
|
||||
function __construct($type, $email)
|
||||
{
|
||||
$this->email = $email;
|
||||
$this->type = $type;
|
||||
}
|
||||
}
|
||||
|
||||
class vcard_source_data_homepage
|
||||
{
|
||||
public $homepage, $type;
|
||||
|
||||
function __construct($type, $homepage)
|
||||
{
|
||||
$this->homepage = $homepage;
|
||||
$this->type = $type;
|
||||
}
|
||||
}
|
||||
|
||||
class vcard_source_data_telephone
|
||||
{
|
||||
public $telephone, $type;
|
||||
|
||||
function __construct($type, $telephone)
|
||||
{
|
||||
$this->telephone = $telephone;
|
||||
$this->type = $type;
|
||||
}
|
||||
}
|
||||
|
||||
class vcard_source_data_socialnetwork
|
||||
{
|
||||
public $nick, $type, $url;
|
||||
|
||||
function __construct($type, $nick, $url)
|
||||
{
|
||||
$this->nick = $nick;
|
||||
$this->type = $type;
|
||||
$this->url = $url;
|
||||
}
|
||||
}
|
||||
|
||||
class vcard_source_data_address
|
||||
{
|
||||
public $street, $street2, $zip, $city, $country, $type;
|
||||
}
|
||||
|
||||
class vcard_source_data_photo
|
||||
{
|
||||
public $binarydata;
|
||||
public $width, $height;
|
||||
public $type;
|
||||
}
|
||||
|
||||
class vcard_source_data
|
||||
{
|
||||
function __construct($name_first, $name_middle, $name_last)
|
||||
{
|
||||
$this->name_first = $name_first;
|
||||
$this->name_middle = $name_middle;
|
||||
$this->name_last = $name_last;
|
||||
}
|
||||
|
||||
public $name_first, $name_middle, $name_last;
|
||||
public $last_update;
|
||||
public $picture_data;
|
||||
|
||||
/** @var array|vcard_source_data_telephone[] $telephones */
|
||||
public $telephones;
|
||||
|
||||
/** @var array|vcard_source_data_homepage[] $homepages */
|
||||
public $homepages;
|
||||
|
||||
/** @var array|vcard_source_data_socialnetwork[] $socialnetworks */
|
||||
public $socialnetworks;
|
||||
|
||||
/** @var array|vcard_source_data_email[] $email */
|
||||
public $emails;
|
||||
|
||||
/** @var array|vcard_source_data_address[] $addresses */
|
||||
public $addresses;
|
||||
|
||||
/** @var vcard_source_data_photo */
|
||||
public $photo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param vcard_source_data $vcardsource
|
||||
* @return string
|
||||
*/
|
||||
function vcard_source_compile($vcardsource)
|
||||
{
|
||||
$str = "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Friendica//DAV-Plugin//EN\r\n";
|
||||
$str .= "N:" . str_replace(";", ",", $vcardsource->name_last) . ";" . str_replace(";", ",", $vcardsource->name_first) . ";" . str_replace(";", ",", $vcardsource->name_middle) . ";;\r\n";
|
||||
$str .= "FN:" . str_replace(";", ",", $vcardsource->name_first) . " " . str_replace(";", ",", $vcardsource->name_middle) . " " . str_replace(";", ",", $vcardsource->name_last) . "\r\n";
|
||||
$str .= "REV:" . str_replace(" ", "T", $vcardsource->last_update) . "Z\r\n";
|
||||
|
||||
$item_count = 0;
|
||||
for ($i = 0; $i < count($vcardsource->homepages); $i++) {
|
||||
if ($i == 0) $str .= "URL;type=" . $vcardsource->homepages[0]->type . ":" . $vcardsource->homepages[0]->homepage . "\r\n";
|
||||
else {
|
||||
$c = ++$item_count;
|
||||
$str .= "item$c.URL;type=" . $vcardsource->homepages[0]->type . ":" . $vcardsource->homepages[0]->homepage . "\r\n";
|
||||
$str .= "item$c.X-ABLabel:_\$!<HomePage>!\$_\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (is_object($vcardsource->photo)) {
|
||||
$data = base64_encode($vcardsource->photo->binarydata);
|
||||
$str .= "PHOTO;ENCODING=BASE64;TYPE=" . $vcardsource->photo->type . ":" . $data . "\r\n";
|
||||
}
|
||||
|
||||
if (isset($vcardsource->socialnetworks) && is_array($vcardsource->socialnetworks)) foreach ($vcardsource->socialnetworks as $netw) switch ($netw->type) {
|
||||
case "dfrn":
|
||||
$str .= "X-SOCIALPROFILE;type=dfrn;x-user=" . $netw->nick . ":" . $netw->url . "\r\n";
|
||||
break;
|
||||
case "facebook":
|
||||
$str .= "X-SOCIALPROFILE;type=facebook;x-user=" . $netw->nick . ":" . $netw->url . "\r\n";
|
||||
break;
|
||||
case "twitter":
|
||||
$str .= "X-SOCIALPROFILE;type=twitter;x-user=" . $netw->nick . ":" . $netw->url . "\r\n";
|
||||
break;
|
||||
}
|
||||
|
||||
$str .= "END:VCARD\r\n";
|
||||
return $str;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $phpDate (UTC)
|
||||
* @return string (Lokalzeit)
|
||||
*/
|
||||
function wdcal_php2MySqlTime($phpDate)
|
||||
{
|
||||
return date(DateTimeFormat::MYSQL, $phpDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sqlDate
|
||||
* @return int
|
||||
*/
|
||||
function wdcal_mySql2PhpTime($sqlDate)
|
||||
{
|
||||
$ts = DateTime::createFromFormat(DateTimeFormat::MYSQL, $sqlDate);
|
||||
return $ts->format("U");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $myqlDate
|
||||
* @return array
|
||||
*/
|
||||
function wdcal_mySql2icalTime($myqlDate)
|
||||
{
|
||||
$x = explode(" ", $myqlDate);
|
||||
$y = explode("-", $x[0]);
|
||||
$ret = array("year"=> $y[0], "month"=> $y[1], "day"=> $y[2]);
|
||||
$y = explode(":", $x[1]);
|
||||
$ret["hour"] = $y[0];
|
||||
$ret["minute"] = $y[1];
|
||||
$ret["second"] = $y[2];
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @return string
|
||||
*/
|
||||
function icalendar_sanitize_string($str = "")
|
||||
{
|
||||
return preg_replace("/[\\r\\n]+/siu", "\r\n", $str);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Sabre_CalDAV_AnimexxCalendarRootNode
|
||||
*/
|
||||
function dav_createRootCalendarNode()
|
||||
{
|
||||
$backends = array(Sabre_CalDAV_Backend_Private::getInstance());
|
||||
foreach ($GLOBALS["CALDAV_PRIVATE_SYSTEM_BACKENDS"] as $backendclass) $backends[] = $backendclass::getInstance();
|
||||
return new Sabre_CalDAV_AnimexxCalendarRootNode(Sabre_DAVACL_PrincipalBackend_Std::getInstance(), $backends);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Sabre_CardDAV_AddressBookRootFriendica
|
||||
*/
|
||||
function dav_createRootContactsNode()
|
||||
{
|
||||
$backends = array(Sabre_CardDAV_Backend_Std::getInstance());
|
||||
foreach ($GLOBALS["CARDDAV_PRIVATE_SYSTEM_BACKENDS"] as $backendclass) $backends[] = $backendclass::getInstance();
|
||||
|
||||
return new Sabre_CardDAV_AddressBookRootFriendica(Sabre_DAVACL_PrincipalBackend_Std::getInstance(), $backends);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
if (CALDAV_URL_PREFIX != "") $server->setBaseUri(CALDAV_URL_PREFIX);
|
||||
|
||||
$authPlugin = new Sabre_DAV_Auth_Plugin(Sabre_DAV_Auth_Backend_Std::getInstance(), DAV_APPNAME);
|
||||
$server->addPlugin($authPlugin);
|
||||
|
||||
if ($needs_caldav) {
|
||||
$caldavPlugin = new Sabre_CalDAV_Plugin();
|
||||
$server->addPlugin($caldavPlugin);
|
||||
}
|
||||
if ($needs_carddav) {
|
||||
$carddavPlugin = new Sabre_CardDAV_Plugin();
|
||||
$server->addPlugin($carddavPlugin);
|
||||
}
|
||||
|
||||
if ($GLOBALS["CALDAV_ACL_PLUGIN_CLASS"] != "") {
|
||||
$aclPlugin = new $GLOBALS["CALDAV_ACL_PLUGIN_CLASS"]();
|
||||
$aclPlugin->defaultUsernamePath = "principals/users";
|
||||
$server->addPlugin($aclPlugin);
|
||||
} else {
|
||||
$aclPlugin = new Sabre_DAVACL_Plugin();
|
||||
$aclPlugin->defaultUsernamePath = "principals/users";
|
||||
$server->addPlugin($aclPlugin);
|
||||
}
|
||||
|
||||
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") || is_subclass_of($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\VCalendar
|
||||
*/
|
||||
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\VCalendar $vObject
|
||||
*/
|
||||
function dav_create_empty_vevent($uid = "")
|
||||
{
|
||||
if ($uid == "") $uid = uniqid();
|
||||
return Sabre\VObject\Reader::read("BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//" . DAV_APPNAME . "//DAV-Plugin//EN\r\nBEGIN:VEVENT\r\nUID:" . $uid . "@" . dav_compat_get_hostname() .
|
||||
"\r\nDTSTAMP:" . date("Ymd") . "T" . date("His") . "Z\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Sabre\VObject\Component\VCalendar $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;
|
||||
|
||||
return $component;
|
||||
}
|
188
dav/common/calendar_rendering.fnk.php
Normal file
188
dav/common/calendar_rendering.fnk.php
Normal file
|
@ -0,0 +1,188 @@
|
|||
<?php
|
||||
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
|
||||
|
||||
/**
|
||||
* @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->value);
|
||||
|
||||
$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');
|
||||
}
|
||||
|
||||
$timezoneOffset = date("P"); // @TODO Get the actual timezone from the event
|
||||
|
||||
|
||||
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', CONVERT_TZ('%s', '$timezoneOffset', @@session.time_zone), CONVERT_TZ('%s', '$timezoneOffset', @@session.time_zone), %d, %d, %d, '%s')",
|
||||
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendar["id"]), IntVal($calendarobject["id"]), dbesc($event["summary"]), date(DateTimeFormat::MYSQL, $start),
|
||||
date(DateTimeFormat::MYSQL, $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, CONVERT_TZ('%s', '$timezoneOffset', @@session.time_zone), %d)",
|
||||
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($calendar["id"]), IntVal($calendarobject["id"]), $alarm->format(DateTimeFormat::MYSQL), $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;
|
||||
}
|
287
dav/common/dav_caldav_backend_common.inc.php
Normal file
287
dav/common/dav_caldav_backend_common.inc.php
Normal file
|
@ -0,0 +1,287 @@
|
|||
<?php
|
||||
|
||||
abstract class Sabre_CalDAV_Backend_Common extends Sabre_CalDAV_Backend_Abstract
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
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',
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return int
|
||||
*/
|
||||
abstract public function getNamespace();
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @abstract
|
||||
* @return string
|
||||
*/
|
||||
abstract public static function getBackendTypeName();
|
||||
|
||||
|
||||
/**
|
||||
* @param int $calendarId
|
||||
* @param string $sd
|
||||
* @param string $ed
|
||||
* @param string $base_path
|
||||
* @return array
|
||||
*/
|
||||
abstract public function listItemsByRange($calendarId, $sd, $ed, $base_path);
|
||||
|
||||
|
||||
/**
|
||||
* @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];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param Sabre\VObject\Component\VEvent $component
|
||||
* @return int
|
||||
*/
|
||||
public static function getDtEndTimeStamp(&$component)
|
||||
{
|
||||
/** @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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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,
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 mixed $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;
|
||||
|
||||
}
|
||||
|
||||
$this->increaseCalendarCtag($calendarId);
|
||||
|
||||
$valuesSql = array();
|
||||
foreach ($newValues as $fieldName=> $value) $valuesSql[] = "`" . $fieldName . "` = '" . dbesc($value) . "'";
|
||||
if (count($valuesSql) > 0) {
|
||||
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);
|
||||
|
||||
}
|
512
dav/common/dav_caldav_backend_private.inc.php
Normal file
512
dav/common/dav_caldav_backend_private.inc.php
Normal file
|
@ -0,0 +1,512 @@
|
|||
<?php
|
||||
|
||||
use Friendica\Core\L10n;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @return string
|
||||
*/
|
||||
public static function getBackendTypeName()
|
||||
{
|
||||
return L10n::t("Private Events");
|
||||
}
|
||||
|
||||
/**
|
||||
* @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);
|
||||
$timezoneOffset = date("P");
|
||||
|
||||
// @TODO Events, die früher angefangen haben, aber noch andauern
|
||||
$evs = q("SELECT *, CONVERT_TZ(`StartTime`, @@session.time_zone, '$timezoneOffset') StartTime, CONVERT_TZ(`EndTime`, @@session.time_zone, '$timezoneOffset') EndTime
|
||||
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
|
||||
* @throws DAVVersionMismatchException
|
||||
* @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 (!isset($cal["uri"])) throw new DAVVersionMismatchException();
|
||||
if (in_array($cal["uri"], $GLOBALS["CALDAV_PRIVATE_SYSTEM_CALENDARS"])) continue;
|
||||
|
||||
$components = array();
|
||||
if ($cal["has_vevent"]) $components[] = "VEVENT";
|
||||
if ($cal["has_vtodo"]) $components[] = "VTODO";
|
||||
|
||||
$dat = array(
|
||||
"id" => $cal["id"],
|
||||
"uri" => $cal["uri"],
|
||||
"principaluri" => $principalUri,
|
||||
'{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}getctag' => $cal['ctag'] ? $cal['ctag'] : '0',
|
||||
'{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}supported-calendar-component-set' => new Sabre_CalDAV_Property_SupportedCalendarComponentSet($components),
|
||||
"calendar_class" => "Sabre_CalDAV_Calendar_Private",
|
||||
);
|
||||
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|Sabre_DAV_Exception_Conflict
|
||||
* @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_Conflict("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"]);
|
||||
}
|
||||
}
|
186
dav/common/dav_caldav_backend_virtual.inc.php
Normal file
186
dav/common/dav_caldav_backend_virtual.inc.php
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
50
dav/common/dav_caldav_calendar_private.inc.php
Normal file
50
dav/common/dav_caldav_calendar_private.inc.php
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
|
||||
class Sabre_CalDAV_Calendar_Private extends Sabre_CalDAV_Calendar
|
||||
{
|
||||
|
||||
public function getACL()
|
||||
{
|
||||
|
||||
return array(
|
||||
array(
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->calendarInfo['principaluri'],
|
||||
'protected' => true,
|
||||
),
|
||||
/*
|
||||
array(
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{DAV:}write',
|
||||
'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,
|
||||
),
|
||||
*/
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
44
dav/common/dav_caldav_calendar_virtual.inc.php
Normal file
44
dav/common/dav_caldav_calendar_virtual.inc.php
Normal 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,
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
}
|
69
dav/common/dav_caldav_root.inc.php
Normal file
69
dav/common/dav_caldav_root.inc.php
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Users collection
|
||||
*
|
||||
* This object is responsible for generating a collection of users.
|
||||
*
|
||||
* @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_AnimexxCalendarRootNode extends Sabre_DAVACL_AbstractPrincipalCollection {
|
||||
|
||||
/**
|
||||
* CalDAV backend
|
||||
*
|
||||
* @var array|Sabre_CalDAV_Backend_Abstract[]
|
||||
*/
|
||||
protected $caldavBackends;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* This constructor needs both an authentication and a caldav backend.
|
||||
*
|
||||
* @param Sabre_DAVACL_IPrincipalBackend $principalBackend
|
||||
* @param array|Sabre_CalDAV_Backend_Abstract[] $caldavBackends
|
||||
* @param string $principalPrefix
|
||||
*/
|
||||
public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend,$caldavBackends, $principalPrefix = 'principals/users') {
|
||||
|
||||
parent::__construct($principalBackend, $principalPrefix);
|
||||
$this->caldavBackends = $caldavBackends;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nodename
|
||||
*
|
||||
* We're overriding this, because the default will be the 'principalPrefix',
|
||||
* and we want it to be Sabre_CalDAV_Plugin::CALENDAR_ROOT
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
return Sabre_CalDAV_Plugin::CALENDAR_ROOT;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a node for a principal.
|
||||
*
|
||||
* The passed array contains principal information, and is guaranteed to
|
||||
* at least contain a uri item. Other properties may or may not be
|
||||
* supplied by the authentication backend.
|
||||
*
|
||||
* @param array $principal
|
||||
* @return \Sabre_CalDAV_AnimexxUserCalendars|\Sabre_DAVACL_IPrincipal
|
||||
*/
|
||||
public function getChildForPrincipal(array $principal) {
|
||||
|
||||
return new Sabre_CalDAV_AnimexxUserCalendars($this->principalBackend, $this->caldavBackends, $principal['uri']);
|
||||
|
||||
}
|
||||
|
||||
}
|
116
dav/common/dav_carddav_backend_common.inc.php
Normal file
116
dav/common/dav_carddav_backend_common.inc.php
Normal file
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
abstract class Sabre_CardDAV_Backend_Common extends Sabre_CardDAV_Backend_Abstract
|
||||
{
|
||||
/**
|
||||
* @abstract
|
||||
* @return int
|
||||
*/
|
||||
abstract public function getNamespace();
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @abstract
|
||||
* @return string
|
||||
*/
|
||||
abstract public static function getBackendTypeName();
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
static private $addressbookCache = array();
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
static private $addressbookObjectCache = array();
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param int $addressbookId
|
||||
* @return array
|
||||
*/
|
||||
static public function loadCalendarById($addressbookId)
|
||||
{
|
||||
if (!isset(self::$addressbookCache[$addressbookId])) {
|
||||
$c = q("SELECT * FROM %s%saddressbooks WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressbookId));
|
||||
self::$addressbookCache[$addressbookId] = $c[0];
|
||||
}
|
||||
return self::$addressbookCache[$addressbookId];
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param int $obj_id
|
||||
* @return array
|
||||
*/
|
||||
static public function loadAddressbookobjectById($obj_id)
|
||||
{
|
||||
if (!isset(self::$addressbookObjectCache[$obj_id])) {
|
||||
$o = q("SELECT * FROM %s%saddressbookobjects WHERE `id` = %d",
|
||||
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($obj_id)
|
||||
);
|
||||
self::$addressbookObjectCache[$obj_id] = $o[0];
|
||||
}
|
||||
return self::$addressbookObjectCache[$obj_id];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates an addressbook's properties
|
||||
*
|
||||
* See Sabre_DAV_IProperties for a description of the mutations array, as
|
||||
* well as the return value.
|
||||
*
|
||||
* @param mixed $addressBookId
|
||||
* @param array $mutations
|
||||
* @throws Sabre_DAV_Exception_Forbidden
|
||||
* @see Sabre_DAV_IProperties::updateProperties
|
||||
* @return bool|array
|
||||
*/
|
||||
public function updateAddressBook($addressBookId, array $mutations)
|
||||
{
|
||||
$updates = array();
|
||||
|
||||
foreach ($mutations as $property=> $newValue) {
|
||||
|
||||
switch ($property) {
|
||||
case '{DAV:}displayname' :
|
||||
$updates['displayname'] = $newValue;
|
||||
break;
|
||||
case '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}addressbook-description' :
|
||||
$updates['description'] = $newValue;
|
||||
break;
|
||||
default :
|
||||
// If any unsupported values were being updated, we must
|
||||
// let the entire request fail.
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// No values are being updated?
|
||||
if (!$updates) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$query = 'UPDATE ' . CALDAV_SQL_DB . CALDAV_SQL_PREFIX . 'addressbooks SET ctag = ctag + 1 ';
|
||||
foreach ($updates as $key=> $value) {
|
||||
$query .= ', `' . dbesc($key) . '` = ' . dbesc($key) . ' ';
|
||||
}
|
||||
$query .= ' WHERE id = ' . IntVal($addressBookId);
|
||||
q($query);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $addressbookId
|
||||
*/
|
||||
protected function increaseAddressbookCtag($addressbookId)
|
||||
{
|
||||
q("UPDATE %s%saddressbooks SET `ctag` = `ctag` + 1 WHERE `id` = '%d'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressbookId));
|
||||
self::$addressbookCache = array();
|
||||
}
|
||||
}
|
277
dav/common/dav_carddav_backend_private.inc.php
Normal file
277
dav/common/dav_carddav_backend_private.inc.php
Normal file
|
@ -0,0 +1,277 @@
|
|||
<?php
|
||||
|
||||
use Friendica\Core\L10n;
|
||||
|
||||
class Sabre_CardDAV_Backend_Std extends Sabre_CardDAV_Backend_Common
|
||||
{
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getNamespace()
|
||||
{
|
||||
return CARDDAV_NAMESPACE_PRIVATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @return string
|
||||
*/
|
||||
public static function getBackendTypeName()
|
||||
{
|
||||
return L10n::t("Private Addressbooks");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of addressbooks for a specific user.
|
||||
*
|
||||
* @param string $principalUri
|
||||
* @return array
|
||||
*/
|
||||
public function getAddressBooksForUser($principalUri)
|
||||
{
|
||||
$n = dav_compat_principal2namespace($principalUri);
|
||||
if ($n["namespace"] != $this->getNamespace()) return array();
|
||||
|
||||
$addressBooks = array();
|
||||
|
||||
$books = q("SELECT * FROM %s%saddressbooks WHERE `namespace` = %d AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($n["namespace"]), IntVal($n["namespace_id"]));
|
||||
foreach ($books as $row) {
|
||||
if (in_array($row["uri"], $GLOBALS["CARDDAV_PRIVATE_SYSTEM_ADDRESSBOOKS"])) continue;
|
||||
|
||||
$addressBooks[] = array(
|
||||
'id' => $row['id'],
|
||||
'uri' => $row['uri'],
|
||||
'principaluri' => $principalUri,
|
||||
'{DAV:}displayname' => $row['displayname'],
|
||||
'{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'],
|
||||
'{http://calendarserver.org/ns/}getctag' => $row['ctag'],
|
||||
'{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}supported-address-data' =>
|
||||
new Sabre_CardDAV_Property_SupportedAddressData(),
|
||||
);
|
||||
}
|
||||
|
||||
return $addressBooks;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new address book
|
||||
*
|
||||
* @param string $principalUri
|
||||
* @param string $url Just the 'basename' of the url.
|
||||
* @param array $properties
|
||||
* @throws Sabre_DAV_Exception_BadRequest
|
||||
* @return void
|
||||
*/
|
||||
public function createAddressBook($principalUri, $url, array $properties)
|
||||
{
|
||||
$uid = dav_compat_principal2uid($principalUri);
|
||||
|
||||
$values = array(
|
||||
'displayname' => null,
|
||||
'description' => null,
|
||||
'principaluri' => $principalUri,
|
||||
'uri' => $url,
|
||||
);
|
||||
|
||||
foreach ($properties as $property=> $newValue) {
|
||||
|
||||
switch ($property) {
|
||||
case '{DAV:}displayname' :
|
||||
$values['displayname'] = $newValue;
|
||||
break;
|
||||
case '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}addressbook-description' :
|
||||
$values['description'] = $newValue;
|
||||
break;
|
||||
default :
|
||||
throw new Sabre_DAV_Exception_BadRequest('Unknown property: ' . $property);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
q("INSERT INTO %s%saddressbooks (`uri`, `displayname`, `description`, `namespace`, `namespace_id`, `ctag`) VALUES ('%s', '%s', '%s', %d, %d, 1)",
|
||||
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($values["uri"]), dbesc($values["displayname"]), dbesc($values["description"]), CARDDAV_NAMESPACE_PRIVATE, IntVal($uid)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an entire addressbook and all its contents
|
||||
*
|
||||
* @param int $addressBookId
|
||||
* @throws Sabre_DAV_Exception_Forbidden
|
||||
* @return void
|
||||
*/
|
||||
public function deleteAddressBook($addressBookId)
|
||||
{
|
||||
q("DELETE FROM %s%saddressbookobjects WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressBookId));
|
||||
q("DELETE FROM %s%saddressbooks WHERE `addressbook_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressBookId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all cards for a specific addressbook id.
|
||||
*
|
||||
* This method should return the following properties for each card:
|
||||
* * carddata - raw vcard data
|
||||
* * uri - Some unique url
|
||||
* * lastmodified - A unix timestamp
|
||||
*
|
||||
* It's recommended to also return the following properties:
|
||||
* * etag - A unique etag. This must change every time the card changes.
|
||||
* * size - The size of the card in bytes.
|
||||
*
|
||||
* If these last two properties are provided, less time will be spent
|
||||
* calculating them. If they are specified, you can also ommit carddata.
|
||||
* This may speed up certain requests, especially with large cards.
|
||||
*
|
||||
* @param string $addressbookId
|
||||
* @return array
|
||||
*/
|
||||
public function getCards($addressbookId)
|
||||
{
|
||||
$r = q('SELECT `id`, `carddata`, `uri`, `lastmodified`, `etag`, `size`, `contact` FROM %s%saddressbookobjects WHERE `addressbook_id` = %d AND `manually_deleted` = 0',
|
||||
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressbookId)
|
||||
);
|
||||
if ($r) return $r;
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a specfic card.
|
||||
*
|
||||
* The same set of properties must be returned as with getCards. The only
|
||||
* exception is that 'carddata' is absolutely required.
|
||||
*
|
||||
* @param mixed $addressBookId
|
||||
* @param string $cardUri
|
||||
* @throws Sabre_DAV_Exception_NotFound
|
||||
* @return array
|
||||
*/
|
||||
public function getCard($addressBookId, $cardUri)
|
||||
{
|
||||
$x = q("SELECT `id`, `carddata`, `uri`, `lastmodified`, `etag`, `size` FROM %s%saddressbookobjects WHERE `addressbook_id` = %d AND `uri` = '%s'",
|
||||
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressBookId), dbesc($cardUri));
|
||||
if (count($x) == 0) throw new Sabre_DAV_Exception_NotFound();
|
||||
return $x[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new card.
|
||||
*
|
||||
* The addressbook id will be passed as the first argument. This is the
|
||||
* same id as it is returned from the getAddressbooksForUser method.
|
||||
*
|
||||
* The cardUri is a base uri, and doesn't include the full path. The
|
||||
* cardData argument is the vcard body, and is passed as a string.
|
||||
*
|
||||
* It is possible to return an ETag from this method. This ETag is for the
|
||||
* newly created resource, and must be enclosed with double quotes (that
|
||||
* is, the string itself must contain the double quotes).
|
||||
*
|
||||
* You should only return the ETag if you store the carddata as-is. If a
|
||||
* subsequent GET request on the same card does not have the same body,
|
||||
* byte-by-byte and you did return an ETag here, clients tend to get
|
||||
* confused.
|
||||
*
|
||||
* If you don't return an ETag, you can just return null.
|
||||
*
|
||||
* @param string $addressBookId
|
||||
* @param string $cardUri
|
||||
* @param string $cardData
|
||||
* @throws Sabre_DAV_Exception_Forbidden
|
||||
* @return string
|
||||
*/
|
||||
public function createCard($addressBookId, $cardUri, $cardData)
|
||||
{
|
||||
$etag = md5($cardData);
|
||||
q("INSERT INTO %s%saddressbookobjects (`carddata`, `uri`, `lastmodified`, `addressbook_id`, `etag`, `size`) VALUES ('%s', '%s', NOW(), %d, '%s', %d)",
|
||||
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($cardData), dbesc($cardUri), IntVal($addressBookId), dbesc($etag), strlen($cardData)
|
||||
);
|
||||
|
||||
q('UPDATE %s%saddressbooks SET `ctag` = `ctag` + 1 WHERE `id` = %d', CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressBookId));
|
||||
|
||||
return '"' . $etag . '"';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a card.
|
||||
*
|
||||
* The addressbook id will be passed as the first argument. This is the
|
||||
* same id as it is returned from the getAddressbooksForUser method.
|
||||
*
|
||||
* The cardUri is a base uri, and doesn't include the full path. The
|
||||
* cardData argument is the vcard body, and is passed as a string.
|
||||
*
|
||||
* It is possible to return an ETag from this method. This ETag should
|
||||
* match that of the updated resource, and must be enclosed with double
|
||||
* quotes (that is: the string itself must contain the actual quotes).
|
||||
*
|
||||
* You should only return the ETag if you store the carddata as-is. If a
|
||||
* subsequent GET request on the same card does not have the same body,
|
||||
* byte-by-byte and you did return an ETag here, clients tend to get
|
||||
* confused.
|
||||
*
|
||||
* If you don't return an ETag, you can just return null.
|
||||
*
|
||||
* @param string $addressBookId
|
||||
* @param string $cardUri
|
||||
* @param string $cardData
|
||||
* @throws Sabre_DAV_Exception_Forbidden
|
||||
* @return string|null
|
||||
*/
|
||||
public function updateCard($addressBookId, $cardUri, $cardData)
|
||||
{
|
||||
$etag = md5($cardData);
|
||||
q("UPDATE %s%saddressbookobjects SET `carddata` = '%s', `lastmodified` = NOW(), `etag` = '%s', `size` = %d, `manually_edited` = 1 WHERE `uri` = '%s' AND `addressbook_id` = %d",
|
||||
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($cardData), dbesc($etag), strlen($cardData), dbesc($cardUri), IntVal($addressBookId)
|
||||
);
|
||||
|
||||
q('UPDATE %s%saddressbooks SET `ctag` = `ctag` + 1 WHERE `id` = %d', CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressBookId));
|
||||
|
||||
return '"' . $etag . '"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a card
|
||||
*
|
||||
* @param string $addressBookId
|
||||
* @param string $cardUri
|
||||
* @throws Sabre_DAV_Exception_Forbidden
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteCard($addressBookId, $cardUri)
|
||||
{
|
||||
q("DELETE FROM %s%saddressbookobjects WHERE `addressbook_id` = %d AND `uri` = '%s'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressBookId), dbesc($cardUri));
|
||||
q('UPDATE %s%saddressbooks SET `ctag` = `ctag` + 1 WHERE `id` = %d', CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressBookId));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
269
dav/common/dav_carddav_backend_virtual.inc.php
Normal file
269
dav/common/dav_carddav_backend_virtual.inc.php
Normal file
|
@ -0,0 +1,269 @@
|
|||
<?php
|
||||
|
||||
abstract class Sabre_CardDAV_Backend_Virtual extends Sabre_CardDAV_Backend_Common
|
||||
{
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @abstract
|
||||
* @param int $addressbookId
|
||||
* @param string $uri
|
||||
* @return array
|
||||
*/
|
||||
/*
|
||||
abstract public function getItemsByUri($addressbookId, $uri);
|
||||
*/
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param int $addressbookId
|
||||
*/
|
||||
static public function invalidateCache($addressbookId) {
|
||||
q("UPDATE %s%saddressbooks SET `needs_rebuild` = 1 WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressbookId));
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @abstract
|
||||
* @param int $addressbookId
|
||||
* @param bool $force
|
||||
*/
|
||||
static abstract protected function createCache_internal($addressbookId, $force = false);
|
||||
|
||||
/**
|
||||
* @param int $addressbookId
|
||||
* @param null|array $addressbook
|
||||
* @param bool $force
|
||||
*/
|
||||
public function createCache($addressbookId, $addressbook = null, $force = false) {
|
||||
$addressbookId = IntVal($addressbookId);
|
||||
|
||||
if (!$addressbook) {
|
||||
$add = q("SELECT `needs_rebuild`, `uri` FROM %s%saddressbooks WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $addressbookId);
|
||||
$addressbook = $add[0];
|
||||
}
|
||||
if ($addressbook["needs_rebuild"] == 1 || $force) {
|
||||
static::createCache_internal($addressbookId, $force);
|
||||
q("UPDATE %s%saddressbooks SET `needs_rebuild` = 0, `ctag` = `ctag` + 1 WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $addressbookId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @abstract
|
||||
* @param int $addressbookId
|
||||
* @param int $contactId
|
||||
* @param bool $force
|
||||
*/
|
||||
static abstract protected function createCardCache($addressbookId, $contactId, $force = false);
|
||||
|
||||
/**
|
||||
* @param int $addressbookId
|
||||
* @return array
|
||||
*/
|
||||
public function getCards($addressbookId)
|
||||
{
|
||||
$addressbookId = IntVal($addressbookId);
|
||||
$add = q("SELECT * FROM %s%saddressbooks WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $addressbookId);
|
||||
if ($add[0]["needs_rebuild"]) {
|
||||
static::createCache_internal($addressbookId);
|
||||
q("UPDATE %s%saddressbooks SET `needs_rebuild` = 0, `ctag` = `ctag` + 1 WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $addressbookId);
|
||||
$add[0]["needs_rebuild"] = 0;
|
||||
$add[0]["ctag"]++;
|
||||
}
|
||||
|
||||
$ret = array();
|
||||
$x = q("SELECT * FROM %s%saddressbookobjects WHERE `addressbook_id` = %d AND `manually_deleted` = 0", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $addressbookId);
|
||||
foreach ($x as $y) $ret[] = self::getCard($addressbookId, $add[0]["uri"], $add[0], $y);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Replaces the x-prop_name value. Replaces the prop_name value IF the old value is the same as the old value of x-prop_name (meaning: the user has not manually changed it)
|
||||
*
|
||||
* @param Sabre\VObject\Component $component
|
||||
* @param string $prop_name
|
||||
* @param string $prop_value
|
||||
* @param array $parameters
|
||||
* @return void
|
||||
*/
|
||||
static public function card_set_automatic_value(&$component, $prop_name, $prop_value, $parameters = array()) {
|
||||
$automatic = $component->select("X-" . $prop_name);
|
||||
$curr = $component->select($prop_name);
|
||||
|
||||
if (count($automatic) == 0) {
|
||||
$prop = new Sabre\VObject\Property('X-' . $prop_name, $prop_value);
|
||||
foreach ($parameters as $key=>$val) $prop->add($key, $val);
|
||||
$component->children[] = $prop;
|
||||
|
||||
if (count($curr) == 0) {
|
||||
$prop = new Sabre\VObject\Property($prop_name, $prop_value);
|
||||
foreach ($parameters as $key=>$val) $prop->add($key, $val);
|
||||
$component->children[] = $prop;
|
||||
}
|
||||
|
||||
} else foreach ($automatic as $auto_prop) {
|
||||
/** @var Sabre\VObject\Property $auto_prop */
|
||||
/** @var Sabre\VObject\Property $actual_prop */
|
||||
foreach ($curr as $actual_prop) {
|
||||
if ($auto_prop->value == $actual_prop->value) $actual_prop->setValue($prop_value);
|
||||
}
|
||||
$auto_prop->setValue($prop_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Deletes the x-prop_name value. Deletes the prop_name value IF the old value is the same as the old value of x-prop_name (meaning: the user has not manually changed it)
|
||||
*
|
||||
* @param Sabre\VObject\Component $component
|
||||
* @param string $prop_name
|
||||
* @param array $parameters
|
||||
*/
|
||||
static public function card_del_automatic_value(&$component, $prop_name, $parameters = array()) {
|
||||
// @TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $addressbookId
|
||||
* @param string $objectUri
|
||||
* @param array $book
|
||||
* @param array $obj
|
||||
* @throws Sabre_DAV_Exception_NotFound
|
||||
* @return array
|
||||
*/
|
||||
public function getCard($addressbookId, $objectUri, $book = null, $obj = null)
|
||||
{
|
||||
$addressbookId = IntVal($addressbookId);
|
||||
|
||||
if ($book == null) {
|
||||
$add = q("SELECT `needs_rebuild`, `uri` FROM %s%saddressbooks WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $addressbookId);
|
||||
$book = $add[0];
|
||||
}
|
||||
if ($book["needs_rebuild"] == 1) {
|
||||
static::createCache_internal($addressbookId);
|
||||
q("UPDATE %s%saddressbooks SET `needs_rebuild` = 0, `ctag` = `ctag` + 1 WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $addressbookId);
|
||||
$add[0]["needs_rebuild"] = 0;
|
||||
}
|
||||
|
||||
if ($obj == null) {
|
||||
$r = q("SELECT * FROM %s%saddressbookobjects WHERE `uri` = '%s' AND `addressbook_id` = %d AND `manually_deleted` = 0",
|
||||
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($objectUri), IntVal($addressbookId));
|
||||
if (count($r) == 0) throw new Sabre_DAV_Exception_NotFound();
|
||||
$obj = $r[0];
|
||||
if ($obj["needs_rebuild"] == 1) $obj = static::createCardCache($addressbookId, $obj["contact"]);
|
||||
}
|
||||
|
||||
$ret = array(
|
||||
"id" => IntVal($obj["uri"]),
|
||||
"carddata" => $obj["carddata"],
|
||||
"uri" => $obj["uri"],
|
||||
"lastmodified" => $obj["lastmodified"],
|
||||
"addressbookid" => $addressbookId,
|
||||
"etag" => $obj["etag"],
|
||||
"size" => IntVal($obj["size"]),
|
||||
);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param string $principalUri
|
||||
* @param string $addressbookUri
|
||||
* @param array $properties
|
||||
* @throws Sabre_DAV_Exception_Forbidden
|
||||
* @return void
|
||||
*/
|
||||
public function createAddressBook($principalUri, $addressbookUri, array $properties)
|
||||
{
|
||||
throw new Sabre_DAV_Exception_Forbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $addressbookId
|
||||
* @throws Sabre_DAV_Exception_Forbidden
|
||||
* @return void
|
||||
*/
|
||||
public function deleteAddressBook($addressbookId)
|
||||
{
|
||||
throw new Sabre_DAV_Exception_Forbidden();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $addressbookId
|
||||
* @param string $objectUri
|
||||
* @param string $cardData
|
||||
* @throws Sabre_DAV_Exception_Forbidden
|
||||
* @return null|string|void
|
||||
*/
|
||||
function createCard($addressbookId, $objectUri, $cardData)
|
||||
{
|
||||
throw new Sabre_DAV_Exception_Forbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a card.
|
||||
*
|
||||
* The addressbook id will be passed as the first argument. This is the
|
||||
* same id as it is returned from the getAddressbooksForUser method.
|
||||
*
|
||||
* The cardUri is a base uri, and doesn't include the full path. The
|
||||
* cardData argument is the vcard body, and is passed as a string.
|
||||
*
|
||||
* It is possible to return an ETag from this method. This ETag should
|
||||
* match that of the updated resource, and must be enclosed with double
|
||||
* quotes (that is: the string itself must contain the actual quotes).
|
||||
*
|
||||
* You should only return the ETag if you store the carddata as-is. If a
|
||||
* subsequent GET request on the same card does not have the same body,
|
||||
* byte-by-byte and you did return an ETag here, clients tend to get
|
||||
* confused.
|
||||
*
|
||||
* If you don't return an ETag, you can just return null.
|
||||
*
|
||||
* @param string $addressBookId
|
||||
* @param string $cardUri
|
||||
* @param string $cardData
|
||||
* @throws Sabre_DAV_Exception_Forbidden
|
||||
* @return string|null
|
||||
*/
|
||||
public function updateCard($addressBookId, $cardUri, $cardData)
|
||||
{
|
||||
echo "Die!"; die(); // @TODO
|
||||
$x = explode("-", $addressBookId);
|
||||
|
||||
$etag = md5($cardData);
|
||||
q("UPDATE %s%scards SET carddata = '%s', lastmodified = %d, etag = '%s', size = %d, manually_edited = 1 WHERE uri = '%s' AND namespace = %d AND namespace_id =%d",
|
||||
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($cardData), time(), $etag, strlen($cardData), dbesc($cardUri), IntVal($x[10]), IntVal($x[1])
|
||||
);
|
||||
q('UPDATE %s%saddressbooks_community SET ctag = ctag + 1 WHERE uid = %d', CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($x[1]));
|
||||
|
||||
return '"' . $etag . '"';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Deletes a card
|
||||
*
|
||||
* @param string $addressBookId
|
||||
* @param string $cardUri
|
||||
* @throws Sabre_DAV_Exception_Forbidden
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteCard($addressBookId, $cardUri)
|
||||
{
|
||||
q("UPDATE %s%scards SET `manually_deleted` = 1 WHERE `addressbook_id` = %d AND `uri` = '%s'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressBookId), dbesc($cardUri));
|
||||
q('UPDATE %s%saddressbooks SET ctag = ctag + 1 WHERE `id` = %d', CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressBookId));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
64
dav/common/dav_carddav_root.inc.php
Normal file
64
dav/common/dav_carddav_root.inc.php
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
class Sabre_CardDAV_AddressBookRootFriendica extends Sabre_DAVACL_AbstractPrincipalCollection {
|
||||
|
||||
/**
|
||||
* Principal Backend
|
||||
*
|
||||
* @var Sabre_DAVACL_IPrincipalBackend
|
||||
*/
|
||||
protected $principalBackend;
|
||||
|
||||
/**
|
||||
* CardDAV backend
|
||||
*
|
||||
* @var array|Sabre_CardDAV_Backend_Abstract[]
|
||||
*/
|
||||
protected $carddavBackends;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* This constructor needs both a principal and a carddav backend.
|
||||
*
|
||||
* By default this class will show a list of addressbook collections for
|
||||
* principals in the 'principals' collection. If your main principals are
|
||||
* actually located in a different path, use the $principalPrefix argument
|
||||
* to override this.
|
||||
*
|
||||
* @param Sabre_DAVACL_IPrincipalBackend $principalBackend
|
||||
* @param array|Sabre_CardDAV_Backend_Abstract[] $carddavBackends
|
||||
* @param string $principalPrefix
|
||||
*/
|
||||
public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, $carddavBackends, $principalPrefix = 'principals/users') {
|
||||
|
||||
$this->carddavBackends = $carddavBackends;
|
||||
parent::__construct($principalBackend, $principalPrefix);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the node
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
return Sabre_CardDAV_Plugin::ADDRESSBOOK_ROOT;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a node for a principal.
|
||||
*
|
||||
* The passed array contains principal information, and is guaranteed to
|
||||
* at least contain a uri item. Other properties may or may not be
|
||||
* supplied by the authentication backend.
|
||||
*
|
||||
* @param array $principal
|
||||
* @return Sabre_DAVACL_IPrincipal
|
||||
*/
|
||||
public function getChildForPrincipal(array $principal) {
|
||||
return new Sabre_CardDAV_UserAddressBooksMultiBackend($this->carddavBackends, $principal['uri']);
|
||||
|
||||
}
|
||||
|
||||
}
|
264
dav/common/dav_user_addressbooks.inc.php
Normal file
264
dav/common/dav_user_addressbooks.inc.php
Normal file
|
@ -0,0 +1,264 @@
|
|||
<?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_CardDAV_UserAddressBooksMultiBackend extends Sabre_DAV_Collection implements Sabre_DAV_IExtendedCollection, Sabre_DAVACL_IACL {
|
||||
|
||||
/**
|
||||
* Principal uri
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $principalUri;
|
||||
|
||||
/**
|
||||
* carddavBackend
|
||||
*
|
||||
* @var array|Sabre_CardDAV_Backend_Abstract[]
|
||||
*/
|
||||
protected $carddavBackends;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array|Sabre_CardDAV_Backend_Abstract[] $carddavBackends
|
||||
* @param string $principalUri
|
||||
*/
|
||||
public function __construct($carddavBackends, $principalUri) {
|
||||
|
||||
$this->carddavBackends = $carddavBackends;
|
||||
$this->principalUri = $principalUri;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this object
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
list(,$name) = Sabre_DAV_URLUtil::splitPath($this->principalUri);
|
||||
return $name;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the name of this object
|
||||
*
|
||||
* @param string $name
|
||||
* @throws Sabre_DAV_Exception_MethodNotAllowed
|
||||
* @return void
|
||||
*/
|
||||
public function setName($name) {
|
||||
|
||||
throw new Sabre_DAV_Exception_MethodNotAllowed();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this object
|
||||
*
|
||||
* @throws Sabre_DAV_Exception_MethodNotAllowed
|
||||
* @return void
|
||||
*/
|
||||
public function delete() {
|
||||
|
||||
throw new Sabre_DAV_Exception_MethodNotAllowed();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last modification date
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLastModified() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new file under this object.
|
||||
*
|
||||
* This is currently not allowed
|
||||
*
|
||||
* @param string $filename
|
||||
* @param resource $data
|
||||
* @throws Sabre_DAV_Exception_MethodNotAllowed
|
||||
* @return null|string|void
|
||||
*/
|
||||
public function createFile($filename, $data=null) {
|
||||
|
||||
throw new Sabre_DAV_Exception_MethodNotAllowed('Creating new files in this collection is not supported');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new directory under this object.
|
||||
*
|
||||
* This is currently not allowed.
|
||||
*
|
||||
* @param string $filename
|
||||
* @throws Sabre_DAV_Exception_MethodNotAllowed
|
||||
* @return void
|
||||
*/
|
||||
public function createDirectory($filename) {
|
||||
|
||||
throw new Sabre_DAV_Exception_MethodNotAllowed('Creating new collections in this collection is not supported');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single calendar, by name
|
||||
*
|
||||
* @param string $name
|
||||
* @throws Sabre_DAV_Exception_NotFound
|
||||
* @todo needs optimizing
|
||||
* @return \Sabre_CardDAV_AddressBook|\Sabre_DAV_INode
|
||||
*/
|
||||
public function getChild($name) {
|
||||
|
||||
foreach($this->getChildren() as $child) {
|
||||
if ($name==$child->getName())
|
||||
return $child;
|
||||
|
||||
}
|
||||
throw new Sabre_DAV_Exception_NotFound('Addressbook with name \'' . $name . '\' could not be found');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of addressbooks
|
||||
*
|
||||
* @return array|Sabre_DAV_INode[]
|
||||
*/
|
||||
public function getChildren() {
|
||||
|
||||
$objs = array();
|
||||
foreach ($this->carddavBackends as $backend) {
|
||||
$addressbooks = $backend->getAddressbooksForUser($this->principalUri);
|
||||
foreach($addressbooks as $addressbook) {
|
||||
$objs[] = new Sabre_CardDAV_AddressBook($backend, $addressbook);
|
||||
}
|
||||
}
|
||||
return $objs;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new addressbook
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $resourceType
|
||||
* @param array $properties
|
||||
* @throws Sabre_DAV_Exception_InvalidResourceType
|
||||
* @return void
|
||||
*/
|
||||
public function createExtendedCollection($name, array $resourceType, array $properties) {
|
||||
|
||||
if (!in_array('{'.Sabre_CardDAV_Plugin::NS_CARDDAV.'}addressbook',$resourceType) || count($resourceType)!==2) {
|
||||
throw new Sabre_DAV_Exception_InvalidResourceType('Unknown resourceType for this collection');
|
||||
}
|
||||
$this->carddavBackends[0]->createAddressBook($this->principalUri, $name, $properties);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getOwner() {
|
||||
|
||||
return $this->principalUri;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getGroup() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->principalUri,
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->principalUri,
|
||||
'protected' => true,
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ACL
|
||||
*
|
||||
* This method will receive a list of new ACE's.
|
||||
*
|
||||
* @param array $acl
|
||||
* @throws Sabre_DAV_Exception_MethodNotAllowed
|
||||
* @return void
|
||||
*/
|
||||
public function setACL(array $acl) {
|
||||
|
||||
throw new Sabre_DAV_Exception_MethodNotAllowed('Changing ACL is not yet supported');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of supported privileges for this node.
|
||||
*
|
||||
* The returned data structure is a list of nested privileges.
|
||||
* See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple
|
||||
* standard structure.
|
||||
*
|
||||
* If null is returned from this method, the default privilege set is used,
|
||||
* which is fine for most common usecases.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function getSupportedPrivilegeSet() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
296
dav/common/dav_user_calendars.inc.php
Normal file
296
dav/common/dav_user_calendars.inc.php
Normal file
|
@ -0,0 +1,296 @@
|
|||
<?php
|
||||
|
||||
|
||||
class Sabre_CalDAV_AnimexxUserCalendars implements Sabre_DAV_IExtendedCollection, Sabre_DAVACL_IACL {
|
||||
|
||||
/**
|
||||
* Principal backend
|
||||
*
|
||||
* @var Sabre_DAVACL_IPrincipalBackend
|
||||
*/
|
||||
protected $principalBackend;
|
||||
|
||||
/**
|
||||
* CalDAV backends
|
||||
*
|
||||
* @var array|Sabre_CalDAV_Backend_Common[]
|
||||
*/
|
||||
protected $caldavBackends;
|
||||
|
||||
/**
|
||||
* Principal information
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $principalInfo;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Sabre_DAVACL_IPrincipalBackend $principalBackend
|
||||
* @param array|Sabre_CalDAV_Backend_Common[] $caldavBackends
|
||||
* @param mixed $userUri
|
||||
*/
|
||||
public function __construct(Sabre_DAVACL_IPrincipalBackend $principalBackend, $caldavBackends, $userUri) {
|
||||
|
||||
$this->principalBackend = $principalBackend;
|
||||
$this->caldavBackends = $caldavBackends;
|
||||
$this->principalInfo = $principalBackend->getPrincipalByPath($userUri);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this object
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
list(,$name) = Sabre_DAV_URLUtil::splitPath($this->principalInfo['uri']);
|
||||
return $name;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the name of this object
|
||||
*
|
||||
* @param string $name
|
||||
* @throws Sabre_DAV_Exception_Forbidden
|
||||
* @return void
|
||||
*/
|
||||
public function setName($name) {
|
||||
|
||||
throw new Sabre_DAV_Exception_Forbidden();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this object
|
||||
*
|
||||
* @throws Sabre_DAV_Exception_Forbidden
|
||||
* @return void
|
||||
*/
|
||||
public function delete() {
|
||||
|
||||
throw new Sabre_DAV_Exception_Forbidden();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last modification date
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLastModified() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new file under this object.
|
||||
*
|
||||
* This is currently not allowed
|
||||
*
|
||||
* @param string $filename
|
||||
* @param resource $data
|
||||
* @throws Sabre_DAV_Exception_MethodNotAllowed
|
||||
* @return null|string|void
|
||||
*/
|
||||
public function createFile($filename, $data=null) {
|
||||
|
||||
throw new Sabre_DAV_Exception_MethodNotAllowed('Creating new files in this collection is not supported');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new directory under this object.
|
||||
*
|
||||
* This is currently not allowed.
|
||||
*
|
||||
* @param string $filename
|
||||
* @throws Sabre_DAV_Exception_MethodNotAllowed
|
||||
* @return void
|
||||
*/
|
||||
public function createDirectory($filename) {
|
||||
|
||||
throw new Sabre_DAV_Exception_MethodNotAllowed('Creating new collections in this collection is not supported');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single calendar, by name
|
||||
*
|
||||
* @param string $name
|
||||
* @throws Sabre_DAV_Exception_NotFound
|
||||
* @todo needs optimizing
|
||||
* @return \Sabre_CalDAV_Calendar|\Sabre_DAV_INode
|
||||
*/
|
||||
public function getChild($name) {
|
||||
|
||||
foreach($this->getChildren() as $child) {
|
||||
if ($name==$child->getName())
|
||||
return $child;
|
||||
|
||||
}
|
||||
throw new Sabre_DAV_Exception_NotFound('Calendar with name \'' . $name . '\' could not be found');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a calendar exists.
|
||||
*
|
||||
* @param string $name
|
||||
* @todo needs optimizing
|
||||
* @return bool
|
||||
*/
|
||||
public function childExists($name) {
|
||||
|
||||
foreach($this->getChildren() as $child) {
|
||||
if ($name==$child->getName())
|
||||
return true;
|
||||
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of calendars
|
||||
*
|
||||
* @return array|\Sabre_DAV_INode[]
|
||||
*/
|
||||
|
||||
public function getChildren() {
|
||||
$objs = array();
|
||||
foreach ($this->caldavBackends as $backend) {
|
||||
$calendars = $backend->getCalendarsForUser($this->principalInfo["uri"]);
|
||||
foreach($calendars as $calendar) {
|
||||
$objs[] = new $calendar["calendar_class"]($this->principalBackend, $backend, $calendar);
|
||||
}
|
||||
}
|
||||
return $objs;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new calendar
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $resourceType
|
||||
* @param array $properties
|
||||
* @throws Sabre_DAV_Exception_InvalidResourceType
|
||||
* @return void
|
||||
*/
|
||||
public function createExtendedCollection($name, array $resourceType, array $properties) {
|
||||
|
||||
if (!in_array('{urn:ietf:params:xml:ns:caldav}calendar',$resourceType) || count($resourceType)!==2) {
|
||||
throw new Sabre_DAV_Exception_InvalidResourceType('Unknown resourceType for this collection');
|
||||
}
|
||||
$this->caldavBackends[0]->createCalendar($this->principalInfo['uri'], $name, $properties);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the owner principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getOwner() {
|
||||
|
||||
return $this->principalInfo['uri'];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a group principal
|
||||
*
|
||||
* This must be a url to a principal, or null if there's no owner
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getGroup() {
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->principalInfo['uri'],
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->principalInfo['uri'],
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->principalInfo['uri'] . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{DAV:}write',
|
||||
'principal' => $this->principalInfo['uri'] . '/calendar-proxy-write',
|
||||
'protected' => true,
|
||||
),
|
||||
array(
|
||||
'privilege' => '{DAV:}read',
|
||||
'principal' => $this->principalInfo['uri'] . '/calendar-proxy-read',
|
||||
'protected' => true,
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ACL
|
||||
*
|
||||
* This method will receive a list of new ACE's.
|
||||
*
|
||||
* @param array $acl
|
||||
* @throws Sabre_DAV_Exception_MethodNotAllowed
|
||||
* @return void
|
||||
*/
|
||||
public function setACL(array $acl) {
|
||||
|
||||
throw new Sabre_DAV_Exception_MethodNotAllowed('Changing ACL is not yet supported');
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the list of supported privileges for this node.
|
||||
*
|
||||
* The returned data structure is a list of nested privileges.
|
||||
* See Sabre_DAVACL_Plugin::getDefaultSupportedPrivilegeSet for a simple
|
||||
* standard structure.
|
||||
*
|
||||
* If null is returned from this method, the default privilege set is used,
|
||||
* which is fine for most common usecases.
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
function getSupportedPrivilegeSet()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
221
dav/common/wdcal.js
Normal file
221
dav/common/wdcal.js
Normal file
|
@ -0,0 +1,221 @@
|
|||
function wdcal_edit_getStartEnd() {
|
||||
"use strict";
|
||||
|
||||
var start = $("#cal_start_date").datepicker("getDate");
|
||||
var start_time = $.timePicker("#cal_start_time").getTime();
|
||||
start.setHours(start_time.getHours());
|
||||
start.setMinutes(start_time.getMinutes());
|
||||
|
||||
var end = $("#cal_end_date").datepicker("getDate");
|
||||
var end_time = $.timePicker("#cal_end_time").getTime();
|
||||
end.setHours(end_time.getHours());
|
||||
end.setMinutes(end_time.getMinutes());
|
||||
|
||||
return {"start": start, "end": end};
|
||||
}
|
||||
|
||||
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);
|
||||
$("#cal_start_date").datepicker("setDate", newstart);
|
||||
$.timePicker("#cal_start_time").setTime(newstart);
|
||||
}
|
||||
}
|
||||
|
||||
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]").text($("#rec_yearly_day option[value=bymonthday]").data("orig").replace("#num#", start.getDate()));
|
||||
$("#rec_monthly_day option[value=bymonthday]").text($("#rec_monthly_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]").text($("#rec_yearly_day option[value=bymonthday_neg]").data("orig").replace("#num#", monthlast));
|
||||
$("#rec_monthly_day option[value=bymonthday_neg]").text($("#rec_monthly_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]").text($("#rec_yearly_day option[value=byday]").data("orig").replace("#num#", wk).replace("#wkday#", wkname));
|
||||
$("#rec_monthly_day option[value=byday]").text($("#rec_monthly_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]").text($("#rec_yearly_day option[value=byday_neg]").data("orig").replace("#num#", wk_inv).replace("#wkday#", wkname));
|
||||
$("#rec_monthly_day option[value=byday_neg]").text($("#rec_monthly_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();
|
||||
$("#color_override").on("click", function() {
|
||||
if ($("#color_override").prop("checked")) $("#cal_color_holder").show();
|
||||
else $("#cal_color_holder").hide();
|
||||
});
|
||||
|
||||
$("#cal_start_time").timePicker({ step: 15 }).on("change", wdcal_edit_checktime_startChanged);
|
||||
$("#cal_end_time").timePicker().on("change", wdcal_edit_checktime_endChanged);
|
||||
|
||||
$("#cal_start_date").datepicker({
|
||||
"dateFormat": dateFormat
|
||||
}).on("change", wdcal_edit_checktime_startChanged);
|
||||
$("#cal_end_date").datepicker({
|
||||
"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();
|
||||
}).change();
|
||||
|
||||
$("#cal_allday").on("click change", function() {
|
||||
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());
|
||||
});
|
||||
|
||||
$("#new_alarm_adder a").click(function(ev) {
|
||||
$("#new_alarm").val("1");
|
||||
$("#noti_new_row").show();
|
||||
$("#new_alarm_adder").hide();
|
||||
ev.preventDefault();
|
||||
});
|
||||
|
||||
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();
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function wdcal_edit_calendars_start(dateFormat, base_path) {
|
||||
"use strict";
|
||||
|
||||
$(".cal_color").colorPicker();
|
||||
|
||||
$(".delete_cal").click(function(ev) {
|
||||
if (!confirm("Do you really want to delete this calendar? All events will be moved to another private calendar.")) ev.preventDefault();
|
||||
});
|
||||
|
||||
$(".calendar_add_caller").click(function(ev) {
|
||||
$(".cal_add_row").show();
|
||||
$(this).parents("div").hide();
|
||||
ev.preventDefault();
|
||||
});
|
||||
}
|
2856
dav/common/wdcal/js/jquery.calendar.js
Normal file
2856
dav/common/wdcal/js/jquery.calendar.js
Normal file
File diff suppressed because it is too large
Load diff
210
dav/common/wdcal/js/main.js
Normal file
210
dav/common/wdcal/js/main.js
Normal file
|
@ -0,0 +1,210 @@
|
|||
$(function () {
|
||||
"use strict";
|
||||
|
||||
$.fn.animexxCalendar = function (option) {
|
||||
//(wdcal_view, std_theme, data_feed_url, readonly, height_diff) {
|
||||
|
||||
var url_cal_add = "?";
|
||||
$(this).find(".calselect input[type=checkbox]").each(function() {
|
||||
if ($(this).prop("checked")) url_cal_add += "cal[]=" + $(this).val() + "&";
|
||||
});
|
||||
|
||||
var def = {
|
||||
calendars:[],
|
||||
calendars_show:[],
|
||||
view:"week",
|
||||
theme:0,
|
||||
onWeekOrMonthToDay:wtd,
|
||||
onBeforeRequestData:cal_beforerequest,
|
||||
onAfterRequestData:cal_afterrequest,
|
||||
onRequestDataError:cal_onerror,
|
||||
autoload:true,
|
||||
data_feed_url:"",
|
||||
url:option.data_feed_url + url_cal_add + "method=list",
|
||||
quickAddUrl:option.data_feed_url + url_cal_add + "method=add",
|
||||
quickUpdateUrl:option.data_feed_url + url_cal_add + "method=update",
|
||||
quickDeleteUrl:option.data_feed_url + url_cal_add + "method=remove"
|
||||
};
|
||||
|
||||
option = $.extend(def, option);
|
||||
|
||||
var $animexxcal = $(this),
|
||||
$gridcontainer = $animexxcal.find(".gridcontainer"),
|
||||
$dv = $animexxcal.find(".calhead"),
|
||||
$caltoolbar = $animexxcal.find(".ctoolbar"),
|
||||
$txtdatetimeshow = $animexxcal.find(".txtdatetimeshow"),
|
||||
$loadingpanel = $animexxcal.find(".loadingpanel"),
|
||||
$loaderrpanel = $animexxcal.find(".loaderror");
|
||||
|
||||
var _MH = document.documentElement.clientHeight;
|
||||
var dvH = $dv.height() + 2;
|
||||
|
||||
option.height = _MH - dvH - option.height_diff;
|
||||
if (option.height < 300) option.height = 300;
|
||||
option.eventItems = [];
|
||||
|
||||
$animexxcal.find(".hdtxtshow").datepicker({
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
onSelect: function(dateText, inst) {
|
||||
var r = new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay);
|
||||
var p = $gridcontainer.gotoDate(r).BcalGetOp();
|
||||
if (p && p.datestrshow) {
|
||||
$animexxcal.find(".txtdatetimeshow").text(p.datestrshow);
|
||||
}
|
||||
}
|
||||
});
|
||||
$animexxcal.find(".txtdatetimeshow").css("cursor", "pointer").bind("click", function() {
|
||||
$animexxcal.find(".hdtxtshow").datepicker("show");
|
||||
});
|
||||
|
||||
var p = $gridcontainer.bcalendar(option).BcalGetOp();
|
||||
if (p && p.datestrshow) {
|
||||
$txtdatetimeshow.text(p.datestrshow);
|
||||
}
|
||||
|
||||
$caltoolbar.noSelect();
|
||||
|
||||
function cal_beforerequest(type) {
|
||||
var t = "Lade Daten...";
|
||||
switch (type) {
|
||||
case 1:
|
||||
t = "Lade Daten...";
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
t = "Wird bearbeitete ...";
|
||||
break;
|
||||
}
|
||||
$loaderrpanel.hide();
|
||||
$loadingpanel.html(t).show();
|
||||
}
|
||||
|
||||
function cal_afterrequest(type) {
|
||||
var p = $gridcontainer.BcalGetOp();
|
||||
if (p && p.datestrshow) {
|
||||
$txtdatetimeshow.text(p.datestrshow);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 1:
|
||||
$loadingpanel.hide();
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
$loadingpanel.html("Erfolg!");
|
||||
$gridcontainer.reload();
|
||||
window.setTimeout(function () {
|
||||
$loadingpanel.hide();
|
||||
}, 2000);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function cal_onerror(type, data) {
|
||||
$loaderrpanel.show();
|
||||
}
|
||||
|
||||
function wtd(p) {
|
||||
if (p && p.datestrshow) {
|
||||
$txtdatetimeshow.text(p.datestrshow);
|
||||
}
|
||||
$caltoolbar.find("div.fcurrent").removeClass("fcurrent");
|
||||
$animexxcal.find(".showdaybtn").addClass("fcurrent");
|
||||
}
|
||||
|
||||
//to show day view
|
||||
$animexxcal.find(".showdaybtn").on("click", function (e) {
|
||||
//document.location.href="#day";
|
||||
$caltoolbar.find("div.fcurrent").removeClass("fcurrent");
|
||||
$(this).addClass("fcurrent");
|
||||
var p = $gridcontainer.switchView("day").BcalGetOp();
|
||||
if (p && p.datestrshow) {
|
||||
$txtdatetimeshow.text(p.datestrshow);
|
||||
}
|
||||
e.preventDefault();
|
||||
});
|
||||
//to show week view
|
||||
$animexxcal.find(".showweekbtn").on("click", function (e) {
|
||||
//document.location.href="#week";
|
||||
$caltoolbar.find("div.fcurrent").removeClass("fcurrent");
|
||||
$(this).addClass("fcurrent");
|
||||
var p = $gridcontainer.switchView("week").BcalGetOp();
|
||||
if (p && p.datestrshow) {
|
||||
$txtdatetimeshow.text(p.datestrshow);
|
||||
}
|
||||
e.preventDefault();
|
||||
});
|
||||
//to show month view
|
||||
$animexxcal.find(".showmonthbtn").on("click", function (e) {
|
||||
//document.location.href="#month";
|
||||
$caltoolbar.find("div.fcurrent").removeClass("fcurrent");
|
||||
$(this).addClass("fcurrent");
|
||||
var p = $gridcontainer.switchView("month").BcalGetOp();
|
||||
if (p && p.datestrshow) {
|
||||
$txtdatetimeshow.text(p.datestrshow);
|
||||
}
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
$animexxcal.find(".showreflashbtn").on("click", function (e) {
|
||||
$gridcontainer.reload();
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
//go to today
|
||||
$animexxcal.find(".showtodaybtn").on("click", function (e) {
|
||||
var p = $gridcontainer.gotoDate().BcalGetOp();
|
||||
if (p && p.datestrshow) {
|
||||
$txtdatetimeshow.text(p.datestrshow);
|
||||
}
|
||||
e.preventDefault();
|
||||
|
||||
});
|
||||
//previous date range
|
||||
$animexxcal.find(".sfprevbtn").on("click", function (e) {
|
||||
var p = $gridcontainer.previousRange().BcalGetOp();
|
||||
if (p && p.datestrshow) {
|
||||
$txtdatetimeshow.text(p.datestrshow);
|
||||
}
|
||||
e.preventDefault();
|
||||
});
|
||||
//next date range
|
||||
$animexxcal.find(".sfnextbtn").on("click", function (e) {
|
||||
var p = $gridcontainer.nextRange().BcalGetOp();
|
||||
if (p && p.datestrshow) {
|
||||
$txtdatetimeshow.text(p.datestrshow);
|
||||
}
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
$animexxcal.find(".calselect input[type=checkbox]").on("click change", function() {
|
||||
var url_cal_add = option.data_feed_url + "?";
|
||||
$animexxcal.find(".calselect input[type=checkbox]").each(function() {
|
||||
if ($(this).prop("checked")) url_cal_add += "cal[]=" + $(this).val() + "&";
|
||||
});
|
||||
/*
|
||||
url:option.data_feed_url + url_cal_add + "method=list",
|
||||
quickAddUrl:option.data_feed_url + url_cal_add + "method=add",
|
||||
quickUpdateUrl:option.data_feed_url + url_cal_add + "method=update",
|
||||
quickDeleteUrl:option.data_feed_url + url_cal_add + "method=remove"
|
||||
|
||||
*/
|
||||
var url = url_cal_add + "method=list";
|
||||
var p = $gridcontainer.BcalGetOp();
|
||||
if (p.url != url) {
|
||||
$gridcontainer.BcalSetOp({
|
||||
"url": url_cal_add + "method=list",
|
||||
"quickAddUrl": url_cal_add + "method=add",
|
||||
"quickUpdateUrl": url_cal_add + "method=update",
|
||||
"quickDeleteUrl": url_cal_add + "method=remove"
|
||||
});
|
||||
$gridcontainer.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
38
dav/common/wdcal/js/wdCalendar_lang_DE.js
Normal file
38
dav/common/wdcal/js/wdCalendar_lang_DE.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
var i18n = $.extend({}, i18n || {}, {
|
||||
xgcalendar: {
|
||||
dateformat: {
|
||||
"fulldaykey": "ddMMyyyy",
|
||||
"fulldayshow": "d L yyyy",
|
||||
"separator": ".",
|
||||
"year_index": 2,
|
||||
"month_index": 1,
|
||||
"day_index": 0,
|
||||
"day": "d"
|
||||
},
|
||||
"no_implemented": "Nicht eingebaut",
|
||||
"to_date_view": "Zum aktuellen Datum gehen",
|
||||
"i_undefined": "Undefined",
|
||||
"allday_event": "Ganztages-Termin",
|
||||
"repeat_event": "Wiederholter Termin",
|
||||
"time": "Zeit",
|
||||
"event": "Termin",
|
||||
"location": "Ort",
|
||||
"participant": "Teilnehmer",
|
||||
"get_data_exception": "Exception when getting data",
|
||||
"new_event": "Neuer Termin",
|
||||
"confirm_delete_event": "Diesen Termin wirklich löschen? ",
|
||||
"confrim_delete_event_or_all": "Nur diesen einen Termin löschen, oder alle Wiederholungen? \r\n[OK] für diesen einen, [Abbrechen] für alle.",
|
||||
"data_format_error": "Data format error! ",
|
||||
"invalid_title": "Der Titel des Termins darf nicht leer sein und kein ($<>) enthalten.",
|
||||
"view_no_ready": "View is not ready",
|
||||
"example": "e.g., Treffen in Raum 23",
|
||||
"content": "Was",
|
||||
"create_event": "Termin anlegen",
|
||||
"update_detail": "Details bearbeiten",
|
||||
"click_to_detail": "Details anzeigen",
|
||||
"i_delete": "Löschen",
|
||||
"day_plural": "Tage",
|
||||
"others": "Weitere: ",
|
||||
"item": ""
|
||||
}
|
||||
});
|
38
dav/common/wdcal/js/wdCalendar_lang_EN.js
Normal file
38
dav/common/wdcal/js/wdCalendar_lang_EN.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
var i18n = $.extend({}, i18n || {}, {
|
||||
xgcalendar: {
|
||||
dateformat: {
|
||||
"fulldaykey": "ddMMyyyy",
|
||||
"fulldayshow": "d L yyyy",
|
||||
"separator": ".",
|
||||
"year_index": 2,
|
||||
"month_index": 1,
|
||||
"day_index": 0,
|
||||
"day": "d"
|
||||
},
|
||||
"no_implemented": "Not implemented",
|
||||
"to_date_view": "Go to today",
|
||||
"i_undefined": "Undefined",
|
||||
"allday_event": "All-day event",
|
||||
"repeat_event": "Recurring event",
|
||||
"time": "Time",
|
||||
"event": "Event",
|
||||
"location": "Loaction",
|
||||
"participant": "Attendees",
|
||||
"get_data_exception": "Exception when getting data",
|
||||
"new_event": "New event",
|
||||
"confirm_delete_event": "Do you really want to delete this event?",
|
||||
"confrim_delete_event_or_all": "Do you want to delete this event alone, or all recurrences? \r\n[OK] for this single item, [Abort] for all.",
|
||||
"data_format_error": "Data format error!",
|
||||
"invalid_title": "The title of an event must not be empty and must not contain ($<>).",
|
||||
"view_no_ready": "View is not ready",
|
||||
"example": "e.g., Meeting in room 23",
|
||||
"content": "Title",
|
||||
"create_event": "Create event",
|
||||
"update_detail": "Edit",
|
||||
"click_to_detail": "Show details",
|
||||
"i_delete": "Delete",
|
||||
"day_plural": "days",
|
||||
"others": "More: ",
|
||||
"item": ""
|
||||
}
|
||||
});
|
238
dav/common/wdcal_backend.inc.php
Normal file
238
dav/common/wdcal_backend.inc.php
Normal file
|
@ -0,0 +1,238 @@
|
|||
<?php
|
||||
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
|
||||
/**
|
||||
* @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' => L10n::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(DateTimeFormat::MYSQL, IntVal($_REQUEST["CalendarStartTime"]))), $type);
|
||||
$datetime_end = new Sabre\VObject\Property\DateTime("DTEND");
|
||||
$datetime_end->setDateTime(new DateTime(date(DateTimeFormat::MYSQL, 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' => L10n::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' => L10n::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(DateTimeFormat::MYSQL, IntVal($_REQUEST["CalendarStartTime"]))), $type);
|
||||
$datetime_end = new Sabre\VObject\Property\DateTime("DTEND");
|
||||
$datetime_end->setDateTime(new DateTime(date(DateTimeFormat::MYSQL, 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' => L10n::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' => L10n::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' => L10n::t('No access')));
|
||||
killme();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
echo wdcal_jsonp_encode($ret);
|
||||
killme();
|
||||
}
|
||||
|
326
dav/common/wdcal_configuration.php
Normal file
326
dav/common/wdcal_configuration.php
Normal file
|
@ -0,0 +1,326 @@
|
|||
<?php
|
||||
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\PConfig;
|
||||
|
||||
abstract class wdcal_local
|
||||
{
|
||||
|
||||
const LOCAL_US = 0;
|
||||
const LOCAL_DE = 1;
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @return array|wdcal_local[]
|
||||
*/
|
||||
static function getInstanceClasses() {
|
||||
return array(
|
||||
self::LOCAL_US => "wdcal_local_us",
|
||||
self::LOCAL_DE => "wdcal_local_de",
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param int $config
|
||||
* @return null|wdcal_local
|
||||
*/
|
||||
static function getInstance($config = 0) {
|
||||
$classes = self::getInstanceClasses();
|
||||
if (isset($classes[$config])) return new $classes[$config];
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param int $uid
|
||||
* @return wdcal_local
|
||||
*/
|
||||
static function getInstanceByUser($uid = 0) {
|
||||
$dateformat = PConfig::get($uid, "dav", "dateformat");
|
||||
$format = self::getInstance($dateformat);
|
||||
if ($format == null) $format = self::getInstance(self::LOCAL_US);
|
||||
return $format;
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @abstract
|
||||
* @return string
|
||||
*/
|
||||
abstract static function getLanguageCode();
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @static
|
||||
* @return string
|
||||
*/
|
||||
abstract static function getName();
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @abstract
|
||||
* @return int
|
||||
*/
|
||||
abstract static function getID();
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @return int
|
||||
*/
|
||||
function date_local2timestamp($str) {
|
||||
$x = $this->date_parseLocal($str);
|
||||
return mktime($x["hour"], $x["minute"], $x["second"], $x["month"], $x["day"], $x["year"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param string $str
|
||||
* @return array
|
||||
*/
|
||||
abstract function date_parseLocal($str);
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param int $ts
|
||||
* @return string
|
||||
*/
|
||||
abstract function date_timestamp2local($ts);
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param int $ts
|
||||
* @return string
|
||||
*/
|
||||
abstract function date_timestamp2localDate($ts);
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return int
|
||||
*/
|
||||
abstract function getFirstDayOfWeek();
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return string
|
||||
*/
|
||||
abstract function dateformat_js_dm1();
|
||||
/**
|
||||
* @abstract
|
||||
* @return string
|
||||
*/
|
||||
abstract function dateformat_js_dm2();
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return string
|
||||
*/
|
||||
abstract function dateformat_js_dm3();
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return string
|
||||
*/
|
||||
abstract function dateformat_datepicker_js();
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param int $ts
|
||||
* @return string
|
||||
*/
|
||||
abstract function dateformat_datepicker_php($ts = 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
class wdcal_local_us extends wdcal_local {
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @return string
|
||||
*/
|
||||
static function getLanguageCode() {
|
||||
return "en";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
static function getName() {
|
||||
return L10n::t("U.S. Time Format (mm/dd/YYYY)");
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @return int
|
||||
*/
|
||||
static function getID() {
|
||||
return wdcal_local::LOCAL_US;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @return array
|
||||
*/
|
||||
function date_parseLocal($str) {
|
||||
return date_parse_from_format("m/d/Y H:i", $str);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $ts
|
||||
* @return string
|
||||
*/
|
||||
function date_timestamp2local($ts)
|
||||
{
|
||||
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
|
||||
*/
|
||||
function getFirstDayOfWeek() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function dateformat_js_dm1() {
|
||||
return "W, M/d";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function dateformat_js_dm2() {
|
||||
return "d. L";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function dateformat_js_dm3() {
|
||||
return "d L yyyy";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function dateformat_datepicker_js() {
|
||||
return "mm/dd/yy";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $ts
|
||||
* @return string
|
||||
*/
|
||||
function dateformat_datepicker_php($ts = 0) {
|
||||
return date("m/d/Y", $ts);
|
||||
}
|
||||
}
|
||||
|
||||
class wdcal_local_de extends wdcal_local {
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @return string
|
||||
*/
|
||||
static function getLanguageCode() {
|
||||
return "de";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
static function getName() {
|
||||
return L10n::t("German Time Format (dd.mm.YYYY)");
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @return int
|
||||
*/
|
||||
static function getID() {
|
||||
return wdcal_local::LOCAL_DE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @return array
|
||||
*/
|
||||
function date_parseLocal($str)
|
||||
{
|
||||
return date_parse_from_format("d.m.Y H:i", $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $ts
|
||||
* @return string
|
||||
*/
|
||||
function date_timestamp2local($ts)
|
||||
{
|
||||
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
|
||||
*/
|
||||
function getFirstDayOfWeek() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function dateformat_js_dm1() {
|
||||
return "W, d.M";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function dateformat_js_dm2() {
|
||||
return "d. L";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function dateformat_js_dm3() {
|
||||
return "d L yyyy";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
function dateformat_datepicker_js() {
|
||||
return "dd.mm.yy";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $ts
|
||||
* @return string
|
||||
*/
|
||||
function dateformat_datepicker_php($ts = 0) {
|
||||
return date("d.m.Y", $ts);
|
||||
}
|
||||
}
|
||||
|
811
dav/common/wdcal_edit.inc.php
Normal file
811
dav/common/wdcal_edit.inc.php
Normal file
|
@ -0,0 +1,811 @@
|
|||
<?php
|
||||
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
|
||||
/**
|
||||
* @param wdcal_local $localization
|
||||
* @param string $baseurl
|
||||
* @param int $calendar_id
|
||||
* @param int $uri
|
||||
* @return string
|
||||
*/
|
||||
function wdcal_getEditPage_str(&$localization, $baseurl, $calendar_id, $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 L10n::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();
|
||||
}
|
||||
|
||||
$notifications = array();
|
||||
$alarms = $component->select("VALARM");
|
||||
foreach ($alarms as $alarm) {
|
||||
/** @var Sabre_VObject_Component_VAlarm $alarm */
|
||||
$action = $alarm->__get("ACTION")->value;
|
||||
$trigger = $alarm->__get("TRIGGER");
|
||||
|
||||
if(isset($trigger['VALUE']) && strtoupper($trigger['VALUE']) !== 'DURATION') {
|
||||
notice("The notification of this event cannot be parsed");
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var DateInterval $triggerDuration */
|
||||
$triggerDuration = Sabre_VObject_DateTimeParser::parseDuration($trigger);
|
||||
$unit = "hour";
|
||||
$value = 1;
|
||||
if ($triggerDuration->s > 0) {
|
||||
$unit = "second";
|
||||
$value = $triggerDuration->s + $triggerDuration->i * 60 + $triggerDuration->h * 3600 + $triggerDuration->d * 3600 * 24; // @TODO support more than days?
|
||||
} elseif ($triggerDuration->i) {
|
||||
$unit = "minute";
|
||||
$value = $triggerDuration->i + $triggerDuration->h * 60 + $triggerDuration->d * 60 * 24;
|
||||
} elseif ($triggerDuration->h) {
|
||||
$unit = "hour";
|
||||
$value = $triggerDuration->h + $triggerDuration->d * 24;
|
||||
} elseif ($triggerDuration->d > 0) {
|
||||
$unit = "day";
|
||||
$value = $triggerDuration->d;
|
||||
}
|
||||
|
||||
$rel = (isset($trigger['RELATED']) && strtoupper($trigger['RELATED']) == 'END') ? 'end' : 'start';
|
||||
|
||||
|
||||
$notifications[] = array(
|
||||
"action" => strtolower($action),
|
||||
"rel" => $rel,
|
||||
"trigger_unit" => $unit,
|
||||
"trigger_value" => $value,
|
||||
);
|
||||
}
|
||||
|
||||
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" => null,
|
||||
);
|
||||
if ($_REQUEST["isallday"]) {
|
||||
$notifications = array();
|
||||
} else {
|
||||
$notifications = array(array("action" => "email", "rel" => "start", "trigger_unit" => "hour", "trigger_value" => 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" => null,
|
||||
);
|
||||
$notifications = array(array("action" => "email", "rel" => "start", "trigger_unit" => "hour", "trigger_value" => 1));
|
||||
$recurrence = null;
|
||||
$recurrentce_exdates = array();
|
||||
}
|
||||
|
||||
$postto = $baseurl . "/dav/wdcal/" . ($uri == 0 ? "new/" : $calendar_id . "/" . $uri . "/edit/");
|
||||
|
||||
$out = "<a href='" . $baseurl . "/dav/wdcal/'>" . L10n::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>" . L10n::t("Event data") . "</h2>";
|
||||
|
||||
$out .= "<label for='calendar' class='block'>" . L10n::t("Calendar") . ":</label><select id='calendar' name='calendar' size='1'>";
|
||||
$found = false;
|
||||
$cal_col = "aaaaaa";
|
||||
foreach ($calendars as $cal) {
|
||||
$prop = $cal->getProperties(array("id", DAV_DISPLAYNAME, DAV_CALENDARCOLOR));
|
||||
$out .= "<option value='" . $prop["id"] . "' ";
|
||||
if ($prop["id"] == $calendar_id) {
|
||||
$out .= "selected";
|
||||
$cal_col = $prop[DAV_CALENDARCOLOR];
|
||||
$found = true;
|
||||
} elseif (!$found) $cal_col = $prop[DAV_CALENDARCOLOR];
|
||||
$out .= ">" . escape_tags($prop[DAV_DISPLAYNAME]) . "</option>\n";
|
||||
}
|
||||
|
||||
$out .= "</select>";
|
||||
$out .= " <label class='plain'><input type='checkbox' name='color_override' id='color_override' ";
|
||||
if (!is_null($event["Color"])) $out .= "checked";
|
||||
$out .= "> " . L10n::t("Special color") . ":</label>";
|
||||
$out .= "<span id='cal_color_holder' ";
|
||||
if (is_null($event["Color"])) $out .= "style='display: none;'";
|
||||
$out .= "><input name='color' id='cal_color' value='" . (is_null($event["Color"]) ? "#" . $cal_col : escape_tags($event["Color"])) . "'></span>";
|
||||
$out .= "<br>\n";
|
||||
|
||||
$out .= "<label class='block' for='cal_summary'>" . L10n::t("Subject") . ":</label>
|
||||
<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_start_date'>" . L10n::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_end_date'>" . L10n::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'>" . L10n::t("Location") . ":</label><input name='location' id='cal_location' value=\"" . escape_tags($event["Location"]) . "\"><br>\n";
|
||||
|
||||
$out .= "<label class='block' for='event-desc-textarea'>" . L10n::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>" . L10n::t("Recurrence") . "</h2>";
|
||||
|
||||
$out .= "<label class='block' for='rec_frequency'>" . L10n::t("Frequency") . ":</label> <select id='rec_frequency' name='rec_frequency' size='1'>";
|
||||
$out .= "<option value=''>" . L10n::t("None") . "</option>\n";
|
||||
$out .= "<option value='daily' ";
|
||||
if ($recurrence && $recurrence->frequency == "daily") $out .= "selected";
|
||||
$out .= ">" . L10n::t("Daily") . "</option>\n";
|
||||
$out .= "<option value='weekly' ";
|
||||
if ($recurrence && $recurrence->frequency == "weekly") $out .= "selected";
|
||||
$out .= ">" . L10n::t("Weekly") . "</option>\n";
|
||||
$out .= "<option value='monthly' ";
|
||||
if ($recurrence && $recurrence->frequency == "monthly") $out .= "selected";
|
||||
$out .= ">" . L10n::t("Monthly") . "</option>\n";
|
||||
$out .= "<option value='yearly' ";
|
||||
if ($recurrence && $recurrence->frequency == "yearly") $out .= "selected";
|
||||
$out .= ">" . L10n::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'>" . L10n::t("days") . "</span>";
|
||||
$time .= "<span class='rec_weekly'>" . L10n::t("weeks") . "</span>";
|
||||
$time .= "<span class='rec_monthly'>" . L10n::t("months") . "</span>";
|
||||
$time .= "<span class='rec_yearly'>" . L10n::t("years") . "</span>";
|
||||
$out .= "<label class='block'>" . L10n::t("Interval") . ":</label> " . str_replace(array("%select%", "%time%"), array($select, $time), L10n::t("All %select% %time%")) . "<br>";
|
||||
|
||||
|
||||
$out .= "<div class='rec_daily'>";
|
||||
$out .= "<label class='block'>" . L10n::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 .= ">" . L10n::t("Sunday") . "</label> ";
|
||||
}
|
||||
$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 .= ">" . L10n::t("Monday") . "</label> ";
|
||||
$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 .= ">" . L10n::t("Tuesday") . "</label> ";
|
||||
$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 .= ">" . L10n::t("Wednesday") . "</label> ";
|
||||
$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 .= ">" . L10n::t("Thursday") . "</label> ";
|
||||
$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 .= ">" . L10n::t("Friday") . "</label> ";
|
||||
$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 .= ">" . L10n::t("Saturday") . "</label> ";
|
||||
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 .= ">" . L10n::t("Sunday") . "</label> ";
|
||||
}
|
||||
$out .= "</div>";
|
||||
|
||||
|
||||
$out .= "<div class='rec_weekly'>";
|
||||
$out .= "<label class='block'>" . L10n::t("Days") . ":</label>";
|
||||
if ($recurrence && $recurrence->byDay) {
|
||||
$byday = $recurrence->byDay;
|
||||
} else {
|
||||
$days = array("MO", "TU", "WE", "TH", "FR", "SA", "SU");
|
||||
$byday = array($days[date("N", $event["StartTime"]) - 1]);
|
||||
}
|
||||
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 .= ">" . L10n::t("Sunday") . "</label> ";
|
||||
}
|
||||
$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 .= ">" . L10n::t("Monday") . "</label> ";
|
||||
$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 .= ">" . L10n::t("Tuesday") . "</label> ";
|
||||
$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 .= ">" . L10n::t("Wednesday") . "</label> ";
|
||||
$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 .= ">" . L10n::t("Thursday") . "</label> ";
|
||||
$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 .= ">" . L10n::t("Friday") . "</label> ";
|
||||
$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 .= ">" . L10n::t("Saturday") . "</label> ";
|
||||
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 .= ">" . L10n::t("Sunday") . "</label> ";
|
||||
}
|
||||
$out .= "<br>";
|
||||
|
||||
$out .= "<label class='block'>" . L10n::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 .= ">" . L10n::t("Sunday") . "</label> ";
|
||||
$out .= "<label class='plain'><input type='radio' name='rec_weekly_wkst' value='MO' ";
|
||||
if ($wkst == "MO") $out .= "checked";
|
||||
$out .= ">" . L10n::t("Monday") . "</label><br>\n";
|
||||
|
||||
$out .= "</div>";
|
||||
|
||||
$monthly_rule = "";
|
||||
if ($recurrence && ($recurrence->frequency == "monthly" || $recurrence->frequency == "yearly")) {
|
||||
if (is_null($recurrence->byDay) && !is_null($recurrence->byMonthDay) && count($recurrence->byMonthDay) == 1) {
|
||||
$day = date("j", $event["StartTime"]);
|
||||
if ($recurrence->byMonthDay[0] == $day) $monthly_rule = "bymonthday";
|
||||
else {
|
||||
$lastday = date("t", $event["StartTime"]);
|
||||
if ($recurrence->byMonthDay[0] == -1 * ($lastday - $day + 1)) $monthly_rule = "bymonthday_neg";
|
||||
}
|
||||
}
|
||||
if (is_null($recurrence->byMonthDay) && !is_null($recurrence->byDay) && count($recurrence->byDay) == 1) {
|
||||
$num = IntVal($recurrence->byDay[0]);
|
||||
/*
|
||||
$dayMap = array(
|
||||
'SU' => 0,
|
||||
'MO' => 1,
|
||||
'TU' => 2,
|
||||
'WE' => 3,
|
||||
'TH' => 4,
|
||||
'FR' => 5,
|
||||
'SA' => 6,
|
||||
);
|
||||
if ($num == 0) {
|
||||
$num = 1;
|
||||
$weekday = $dayMap[$recurrence->byDay[0]];
|
||||
} else {
|
||||
$weekday = $dayMap[substr($recurrence->byDay[0], strlen($num))];
|
||||
}
|
||||
|
||||
echo $num . " - " . $weekday;
|
||||
*/
|
||||
if ($num > 0) $monthly_rule = "byday";
|
||||
if ($num < 0) $monthly_rule = "byday_neg";
|
||||
}
|
||||
if ($monthly_rule == "") notice("The recurrence of this event cannot be parsed");
|
||||
}
|
||||
|
||||
$out .= "<div class='rec_monthly'>";
|
||||
$out .= "<label class='block' for='rec_monthly_day'>" . L10n::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 .= ">" . L10n::t("#num#th of each month") . "</option>\n";
|
||||
$out .= "<option value='bymonthday_neg' ";
|
||||
if ($monthly_rule == "bymonthday_neg") $out .= "selected";
|
||||
$out .= ">" . L10n::t("#num#th-last of each month") . "</option>\n";
|
||||
$out .= "<option value='byday' ";
|
||||
if ($monthly_rule == "byday") $out .= "selected";
|
||||
$out .= ">" . L10n::t("#num#th #wkday# of each month") . "</option>\n";
|
||||
$out .= "<option value='byday_neg' ";
|
||||
if ($monthly_rule == "byday_neg") $out .= "selected";
|
||||
$out .= ">" . L10n::t("#num#th-last #wkday# of each month") . "</option>\n";
|
||||
$out .= "</select>";
|
||||
$out .= "</div>\n";
|
||||
|
||||
if ($recurrence && $recurrence->frequency == "yearly") {
|
||||
if (count($recurrence->byMonth) != 1 || $recurrence->byMonth[0] != date("n", $event["StartTime"])) notice("The recurrence of this event cannot be parsed!");
|
||||
}
|
||||
|
||||
$out .= "<div class='rec_yearly'>";
|
||||
$out .= "<label class='block'>" . L10n::t("Month") . ":</label> <span class='rec_month_name'>#month#</span><br>\n";
|
||||
$out .= "<label class='block' for='rec_yearly_day'>" . L10n::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 .= ">" . L10n::t("#num#th of the given month") . "</option>\n";
|
||||
$out .= "<option value='bymonthday_neg' ";
|
||||
if ($monthly_rule == "bymonthday_neg") $out .= "selected";
|
||||
$out .= ">" . L10n::t("#num#th-last of the given month") . "</option>\n";
|
||||
$out .= "<option value='byday' ";
|
||||
if ($monthly_rule == "byday") $out .= "selected";
|
||||
$out .= ">" . L10n::t("#num#th #wkday# of the given month") . "</option>\n";
|
||||
$out .= "<option value='byday_neg' ";
|
||||
if ($monthly_rule == "byday_neg") $out .= "selected";
|
||||
$out .= ">" . L10n::t("#num#th-last #wkday# of the given 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'>" . L10n::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 .= ">" . L10n::t("Infinite") . "</option>\n";
|
||||
$out .= "<option value='date' ";
|
||||
if ($rule_type == "date") $out .= "selected";
|
||||
$out .= ">" . L10n::t("Until the following date") . ":</option>\n";
|
||||
$out .= "<option value='count' ";
|
||||
if ($rule_type == "count") $out .= "selected";
|
||||
$out .= ">" . L10n::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'>" . L10n::t("Exceptions") . ":</label><div class='rec_exceptions'>";
|
||||
$out .= "<div class='rec_exceptions_none' ";
|
||||
if (count($recurrentce_exdates) > 0) $out .= "style='display: none;'";
|
||||
$out .= ">" . L10n::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>" . L10n::t("Notification") . "</h2>";
|
||||
|
||||
if (!$notifications) $notifications = array();
|
||||
$notifications["new"] = array(
|
||||
"action" => "email",
|
||||
"trigger_value" => 60,
|
||||
"trigger_unit" => "minute",
|
||||
"rel" => "start",
|
||||
);
|
||||
|
||||
foreach ($notifications as $index => $noti) {
|
||||
|
||||
$unparsable = false;
|
||||
if (!in_array($noti["action"], array("email", "display"))) $unparsable = true;
|
||||
|
||||
$out .= "<div class='noti_holder' ";
|
||||
if (!is_numeric($index) && $index == "new") $out .= "style='display: none;' id='noti_new_row'";
|
||||
$out .= "><label class='block' for='noti_type_" . $index . "'>" . L10n::t("Notify by") . ":</label>";
|
||||
$out .= "<select name='noti_type[$index]' size='1' id='noti_type_" . $index . "'>";
|
||||
$out .= "<option value=''>- " . L10n::t("Remove") . " -</option>\n";
|
||||
$out .= "<option value='email' "; if (!$unparsable && $noti["action"] == "email") $out .= "selected"; $out .= ">" . L10n::t("E-Mail") . "</option>\n";
|
||||
$out .= "<option value='display' "; if (!$unparsable && $noti["action"] == "display") $out .= "selected"; $out .= ">" . L10n::t("On Friendica / Display") . "</option>\n";
|
||||
//$out .= "<option value='other' "; if ($unparsable) $out .= "selected"; $out .= ">- " . L10n::t("other (leave it untouched)") . " -</option>\n"; // @TODO
|
||||
$out .= "</select><br>";
|
||||
|
||||
$out .= "<label class='block'>" . L10n::t("Time") . ":</label>";
|
||||
$out .= "<input name='noti_value[$index]' size='5' style='width: 5em;' value='" . $noti["trigger_value"] . "'>";
|
||||
|
||||
$out .= "<select name='noti_unit[$index]' size='1'>";
|
||||
$out .= "<option value='H' "; if ($noti["trigger_unit"] == "hour") $out .= "selected"; $out .= ">" . L10n::t("Hours") . "</option>\n";
|
||||
$out .= "<option value='M' "; if ($noti["trigger_unit"] == "minute") $out .= "selected"; $out .= ">" . L10n::t("Minutes") . "</option>\n";
|
||||
$out .= "<option value='S' "; if ($noti["trigger_unit"] == "second") $out .= "selected"; $out .= ">" . L10n::t("Seconds") . "</option>\n";
|
||||
$out .= "<option value='D' "; if ($noti["trigger_unit"] == "day") $out .= "selected"; $out .= ">" . L10n::t("Days") . "</option>\n";
|
||||
$out .= "<option value='W' "; if ($noti["trigger_unit"] == "week") $out .= "selected"; $out .= ">" . L10n::t("Weeks") . "</option>\n";
|
||||
$out .= "</select>";
|
||||
|
||||
$out .= " <label class='plain'>" . L10n::t("before the") . " <select name='noti_ref[$index]' size='1'>";
|
||||
$out .= "<option value='start' "; if ($noti["rel"] == "start") $out .= "selected"; $out .= ">" . L10n::t("start of the event") . "</option>\n";
|
||||
$out .= "<option value='end' "; if ($noti["rel"] == "end") $out .= "selected"; $out .= ">" . L10n::t("end of the event") . "</option>\n";
|
||||
$out .= "</select></label>\n";
|
||||
|
||||
$out .= "</div>";
|
||||
}
|
||||
$out .= "<input type='hidden' name='new_alarm' id='new_alarm' value='0'><div id='new_alarm_adder'><a href='#'>" . L10n::t("Add a notification") . "</a></div>";
|
||||
|
||||
$out .= "<script>\$(function() {
|
||||
wdcal_edit_init('" . $localization->dateformat_datepicker_js() . "', '${baseurl}/dav/');
|
||||
});</script>";
|
||||
|
||||
$out .= "<br><input type='submit' name='save' value='Save'></form>";
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Sabre_VObject_Component_VEvent $component
|
||||
* @param wdcal_local $localization
|
||||
* @return int
|
||||
*/
|
||||
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(DateTimeFormat::MYSQL, $ts_start)), $type);
|
||||
$datetime_end = new Sabre\VObject\Property\DateTime("DTEND");
|
||||
$datetime_end->setDateTime(new DateTime(date(DateTimeFormat::MYSQL, $ts_end)), $type);
|
||||
|
||||
$component->__unset("DTSTART");
|
||||
$component->__unset("DTEND");
|
||||
$component->add($datetime_start);
|
||||
$component->add($datetime_end);
|
||||
|
||||
return $ts_start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Sabre_VObject_Component_VEvent $component
|
||||
* @param string $str
|
||||
* @return string
|
||||
*/
|
||||
|
||||
function wdcal_set_component_recurrence_special(&$component, $str) {
|
||||
$ret = "";
|
||||
|
||||
/** @var Sabre\VObject\Property\DateTime $start */
|
||||
$start = $component->__get("DTSTART");
|
||||
$dayMap = array(
|
||||
0 => 'SU',
|
||||
1 => 'MO',
|
||||
2 => 'TU',
|
||||
3 => 'WE',
|
||||
4 => 'TH',
|
||||
5 => 'FR',
|
||||
6 => 'SA',
|
||||
);
|
||||
|
||||
switch ($str) {
|
||||
case "bymonthday":
|
||||
$day = $start->getDateTime()->format("j");
|
||||
$ret = ";BYMONTHDAY=" . $day;
|
||||
break;
|
||||
case "bymonthday_neg":
|
||||
$day = $start->getDateTime()->format("j");
|
||||
$day_max = $start->getDateTime()->format("t");
|
||||
$ret = ";BYMONTHDAY=" . (-1 * ($day_max - $day + 1));
|
||||
break;
|
||||
case "byday":
|
||||
$day = $start->getDateTime()->format("j");
|
||||
$weekday = $dayMap[$start->getDateTime()->format("w")];
|
||||
$num = IntVal(ceil($day / 7));
|
||||
$ret = ";BYDAY=${num}${weekday}";
|
||||
break;
|
||||
case "byday_neg":
|
||||
$day = $start->getDateTime()->format("j");
|
||||
$weekday = $dayMap[$start->getDateTime()->format("w")];
|
||||
$day_max = $start->getDateTime()->format("t");
|
||||
$day_last = ($day_max - $day + 1);
|
||||
$num = IntVal(ceil($day_last / 7));
|
||||
$ret = ";BYDAY=-${num}${weekday}";
|
||||
break;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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(DateTimeFormat::MYSQL, $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";
|
||||
$part_freq .= wdcal_set_component_recurrence_special($component, $_REQUEST["rec_monthly_day"]);
|
||||
break;
|
||||
case "yearly":
|
||||
/** @var Sabre\VObject\Property\DateTime $start */
|
||||
$start = $component->__get("DTSTART");
|
||||
$part_freq = "FREQ=YEARLY";
|
||||
$part_freq .= ";BYMONTH=" . $start->getDateTime()->format("n");
|
||||
$part_freq .= wdcal_set_component_recurrence_special($component, $_REQUEST["rec_yearly_day"]);
|
||||
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(DateTimeFormat::MYSQL, $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 Sabre\VObject\Component\VEvent $component
|
||||
* @param wdcal_local $localization
|
||||
* @param string $summary
|
||||
* @param int $dtstart
|
||||
*/
|
||||
function wdcal_set_component_alerts(&$component, &$localization, $summary, $dtstart)
|
||||
{
|
||||
$a = get_app();
|
||||
|
||||
$prev_alarms = $component->select("VALARM");
|
||||
$component->__unset("VALARM");
|
||||
|
||||
foreach ($prev_alarms as $al) {
|
||||
/** @var Sabre\VObject\Component\VAlarm $al */
|
||||
// @TODO Parse notifications that have been there before; e.g. from Lightning
|
||||
}
|
||||
|
||||
foreach (array_keys($_REQUEST["noti_type"]) as $key) if (is_numeric($key) || ($key == "new" && $_REQUEST["new_alarm"] == 1)) {
|
||||
$alarm = new Sabre\VObject\Component\VAlarm("VALARM");
|
||||
|
||||
switch ($_REQUEST["noti_type"][$key]) {
|
||||
case "email":
|
||||
$mailtext = str_replace(array(
|
||||
"#date#", "#name",
|
||||
), array(
|
||||
$localization->date_timestamp2local($dtstart), $summary,
|
||||
), L10n::t("The event #name# will start at #date"));
|
||||
|
||||
$alarm->add(new Sabre\VObject\Property("ACTION", "EMAIL"));
|
||||
$alarm->add(new Sabre\VObject\Property("SUMMARY", $summary));
|
||||
$alarm->add(new Sabre\VObject\Property("DESCRIPTION", $mailtext));
|
||||
$alarm->add(new Sabre\VObject\Property("ATTENDEE", "MAILTO:" . $a->user["email"]));
|
||||
break;
|
||||
case "display":
|
||||
$alarm->add(new Sabre\VObject\Property("ACTION", "DISPLAY"));
|
||||
$text = str_replace("#name#", $summary, L10n::t("#name# is about to begin."));
|
||||
$alarm->add(new Sabre\VObject\Property("DESCRIPTION", $text));
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
$trigger_name = "TRIGGER";
|
||||
$trigger_val = ""; // @TODO Bugfix : und ; sind evtl. vertauscht vgl. http://www.kanzaki.com/docs/ical/trigger.html
|
||||
if ($_REQUEST["noti_ref"][$key] == "end") $trigger_name .= ";RELATED=END";
|
||||
$trigger_val .= "-P";
|
||||
if (in_array($_REQUEST["noti_unit"][$key], array("H", "M", "S"))) $trigger_val .= "T";
|
||||
$trigger_val .= IntVal($_REQUEST["noti_value"][$key]) . $_REQUEST["noti_unit"][$key];
|
||||
$alarm->add(new Sabre\VObject\Property($trigger_name, $trigger_val));
|
||||
|
||||
$component->add($alarm);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uri
|
||||
* @param int $uid
|
||||
* @param string $timezone
|
||||
* @param string $goaway_url
|
||||
* @return array
|
||||
*/
|
||||
function wdcal_postEditPage($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" => L10n::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");
|
||||
}
|
||||
|
||||
$ts_start = wdcal_set_component_date($component, $localization);
|
||||
wdcal_set_component_recurrence($component, $localization);
|
||||
wdcal_set_component_alerts($component, $localization, icalendar_sanitize_string(dav_compat_parse_text_serverside("summary")), $ts_start);
|
||||
|
||||
$component->__unset("LOCATION");
|
||||
$component->__unset("SUMMARY");
|
||||
$component->__unset("DESCRIPTION");
|
||||
$component->__unset("X-ANIMEXX-COLOR");
|
||||
$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")));
|
||||
if (isset($_REQUEST["color_override"])) {
|
||||
$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" => L10n::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 = dav_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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue