mirror of
https://gitlab.com/davical-project/davical.git
synced 2026-08-29 18:26:05 +00:00
Add items to attendee's calendars as well as to their inboxes on PUT.
This commit is contained in:
parent
bdb360f082
commit
4f01fe0a17
@ -4,12 +4,19 @@ include_once('DAVResource.php');
|
||||
class WritableCollection extends DAVResource {
|
||||
|
||||
/**
|
||||
* Writes the data to a member in the collection and returns the segment_name of the resource in our internal namespace.
|
||||
* @param vComponent $data The resource to be written.
|
||||
* Writes the data to a member in the collection and returns the segment_name of the
|
||||
* resource in our internal namespace.
|
||||
*
|
||||
* @param vCalendar $vcal The resource to be written.
|
||||
* @param boolean $create_resource True if this is a new resource.
|
||||
* @param $segment_name The name of the resource within the collection, or false on failure.
|
||||
* @param boolean $do_scheduling True if we should also do scheduling for this write. Default false.
|
||||
* @param string $segment_name The name of the resource within the collection, or null if this
|
||||
* call should invent one based on the UID of the vCalendar.
|
||||
* @param boolean $log_action Whether to log this action. Defaults to false since this is normally called
|
||||
* in situations where one is writing secondary data.
|
||||
* @return string The segment_name of the resource within the collection, as written, or false on failure.
|
||||
*/
|
||||
function WriteCalendarMember( vComponent $data, $create_resource, $do_scheduling=true, $segment_name = null ) {
|
||||
function WriteCalendarMember( vCalendar $vcal, $create_resource, $do_scheduling=false, $segment_name = null, $log_action=false ) {
|
||||
if ( !$this->IsSchedulingCollection() && !$this->IsCalendar() ) {
|
||||
dbg_error_log( 'PUT', '"%s" is not a calendar or scheduling collection!', $this->dav_name);
|
||||
return false;
|
||||
@ -17,7 +24,7 @@ class WritableCollection extends DAVResource {
|
||||
|
||||
global $tz_regex, $session, $caldav_context;
|
||||
|
||||
$resources = $data->GetComponents('VTIMEZONE',false); // Not matching VTIMEZONE
|
||||
$resources = $vcal->GetComponents('VTIMEZONE',false); // Not matching VTIMEZONE
|
||||
$user_no = $this->user_no();
|
||||
$collection_id = $this->collection_id();
|
||||
|
||||
@ -36,7 +43,7 @@ class WritableCollection extends DAVResource {
|
||||
}
|
||||
$path = $this->dav_name() . $segment_name;
|
||||
|
||||
$caldav_data = $data->Render();
|
||||
$caldav_data = $vcal->Render();
|
||||
$etag = md5($caldav_data);
|
||||
$weak_etag = null;
|
||||
|
||||
@ -53,6 +60,7 @@ class WritableCollection extends DAVResource {
|
||||
}
|
||||
if ( $qry->rows() != 1 || !($row = $qry->Fetch()) ) {
|
||||
// No dav_id? => We're toast!
|
||||
dbg_error_log( 'PUT', 'No dav_id!!!', $path);
|
||||
rollback_on_error( $caldav_context, $user_no, $path);
|
||||
return false;
|
||||
}
|
||||
@ -73,13 +81,13 @@ class WritableCollection extends DAVResource {
|
||||
) );
|
||||
|
||||
if ( $create_resource ) {
|
||||
if ( !$this->IsSchedulingCollection() ) create_scheduling_requests($vcal);
|
||||
if ( !$this->IsSchedulingCollection() && $do_scheduling ) do_scheduling_requests($vcal,true);
|
||||
$sql = 'INSERT INTO caldav_data ( dav_id, user_no, dav_name, dav_etag, caldav_data, caldav_type, logged_user, created, modified, collection_id, weak_etag )
|
||||
VALUES( :dav_id, :user_no, :dav_name, :etag, :dav_data, :caldav_type, :session_user, current_timestamp, current_timestamp, :collection_id, :weak_etag )';
|
||||
$dav_params[':collection_id'] = $collection_id;
|
||||
}
|
||||
else {
|
||||
if ( !$this->IsSchedulingCollection() ) update_scheduling_requests($vcal);
|
||||
if ( !$this->IsSchedulingCollection() && $do_scheduling ) do_scheduling_requests($vcal,false);
|
||||
$sql = 'UPDATE caldav_data SET caldav_data=:dav_data, dav_etag=:etag, caldav_type=:caldav_type, logged_user=:session_user,
|
||||
modified=current_timestamp, weak_etag=:weak_etag WHERE dav_id=:dav_id';
|
||||
}
|
||||
@ -168,7 +176,7 @@ class WritableCollection extends DAVResource {
|
||||
$due_prop = $first->GetProperty('DUE');
|
||||
$tzid = $due_prop->GetParameterValue('TZID');
|
||||
}
|
||||
$timezones = $data->GetComponents('VTIMEZONE');
|
||||
$timezones = $vcal->GetComponents('VTIMEZONE');
|
||||
foreach( $timezones AS $k => $tz ) {
|
||||
if ( $tz->GetPValue('TZID') != $tzid ) {
|
||||
/**
|
||||
@ -253,7 +261,7 @@ EOSQL;
|
||||
|
||||
if ( !$this->IsSchedulingCollection() ) {
|
||||
write_alarms($dav_id, $first);
|
||||
write_attendees($dav_id, $first);
|
||||
write_attendees($dav_id, $vcal);
|
||||
if ( $log_action && function_exists('log_caldav_action') ) {
|
||||
log_caldav_action( $put_action_type, $first->GetPValue('UID'), $user_no, $collection_id, $path );
|
||||
}
|
||||
@ -278,25 +286,35 @@ EOSQL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the data to a member in the collection and returns the segment_name of the resource in our internal namespace.
|
||||
* @param $data mixed The resource to be written.
|
||||
* Writes the data to a member in the collection and returns the segment_name of the
|
||||
* resource in our internal namespace.
|
||||
*
|
||||
* A caller who wants scheduling not to happen for this write must already
|
||||
* know they are dealing with a calendar, so should be calling WriteCalendarMember
|
||||
* directly.
|
||||
*
|
||||
* @param $resource mixed The resource to be written.
|
||||
* @param $create_resource boolean True if this is a new resource.
|
||||
* @param $segment_name The name of the resource within the collection, or false on failure.
|
||||
* @param boolean $log_action Whether to log this action. Defaults to true since this is normally called
|
||||
* in situations where one is writing primary data.
|
||||
* @return string The segment_name that was given, or one that was assigned if null was given.
|
||||
*/
|
||||
function WriteMember( $data, $create_resource, $segment_name = null ) {
|
||||
function WriteMember( $resource, $create_resource, $segment_name = null, $log_action=true ) {
|
||||
if ( ! $this->IsCollection() ) {
|
||||
dbg_error_log( 'PUT', '"%s" is not a collection path', $this->dav_name);
|
||||
return false;
|
||||
}
|
||||
if ( ! is_object($data) ) {
|
||||
if ( ! is_object($resource) ) {
|
||||
dbg_error_log( 'PUT', 'No data supplied!' );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $data instanceof vComponent )
|
||||
return $this->WriteCalendarMember($data,$create_resource,$segment_name);
|
||||
else if ( $data instanceof VCard )
|
||||
return $this->WriteAddressbookMember($data,$create_resource,$segment_name);
|
||||
if ( $resource instanceof vCalendar ) {
|
||||
return $this->WriteCalendarMember($resource,$create_resource,true,$segment_name,$log_action);
|
||||
}
|
||||
else if ( $resource instanceof VCard )
|
||||
return $this->WriteAddressbookMember($resource,$create_resource,$segment_name, $log_action);
|
||||
|
||||
return $segment_name;
|
||||
}
|
||||
|
||||
@ -309,83 +309,59 @@ function handle_schedule_reply ( vCalendar $ical ) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a scheduling request in the schedule inbox for the
|
||||
* Create/Update the scheduling requests for this resource. This includes updating
|
||||
* the scheduled user's default calendar.
|
||||
* @param vComponent $resource The VEVENT/VTODO/... resource we are scheduling
|
||||
* @param vProperty $attendee The attendee we are scheduling
|
||||
* @return float The result of the scheduling request, per caldav-sched #3.5.4
|
||||
* @param boolean $create true if the scheduling requests are being created.
|
||||
*/
|
||||
function write_scheduling_request( vComponent $resource, $attendee_value, $create_resource ) {
|
||||
$email = preg_replace( '/^mailto:/i', '', $attendee_value );
|
||||
$schedule_target = new Principal('email',$email);
|
||||
if ( $schedule_target->Exists() ) {
|
||||
$attendee_inbox = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-inbox')));
|
||||
if ( ! $attendee_inbox->HavePrivilegeTo('schedule-deliver-invite') ) {
|
||||
$response = '3.8;'.translate('No authority to deliver invitations to user.');
|
||||
}
|
||||
else if ( $attendee_inbox->WriteCalendarMember($resource, $create_resource) === false ) {
|
||||
$response = '5.3;'.translate('No scheduling support for user');
|
||||
function do_scheduling_requests( vCalendar $resource, $create ) {
|
||||
if ( ! is_object($resource) ) {
|
||||
dbg_error_log( 'PUT', 'do_scheduling_requests called with non-object parameter (%s)', gettype($resource) );
|
||||
return;
|
||||
}
|
||||
|
||||
$attendees = $resource->GetAttendees();
|
||||
if ( count($attendees) == 0 ) {
|
||||
dbg_error_log( 'PUT', 'Event has no attendees - no scheduling required.', count($attendees) );
|
||||
return;
|
||||
}
|
||||
|
||||
dbg_error_log( 'PUT', 'Adding to scheduling inbox %d attendees', count($attendees) );
|
||||
$schedule_request = clone($resource);
|
||||
$schedule_request->AddProperty('METHOD','REQUEST');
|
||||
foreach( $attendees AS $attendee ) {
|
||||
$email = preg_replace( '/^mailto:/i', '', $attendee->Value() );
|
||||
$schedule_target = new Principal('email',$email);
|
||||
if ( $schedule_target->Exists() ) {
|
||||
$attendee_calendar = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-default-calendar')));
|
||||
if ( !$attendee_calendar->Exists() ) {
|
||||
dbg_error_log('ERROR','Default calendar at "%s" does not exist for user "%s"',
|
||||
$attendee_calendar->dav_name(), $schedule_target->username());
|
||||
$response = '5.3;'.translate('No scheduling support for user');
|
||||
}
|
||||
else if ( $attendee_calendar->WriteCalendarMember($resource, $create) === false ) {
|
||||
dbg_error_log('ERROR','Could not write new calendar member to %s', $attendee_calendar->dav_name(),
|
||||
$attendee_calendar->dav_name(), $schedule_target->username());
|
||||
$response = '5.3;'.translate('No scheduling support for user');
|
||||
}
|
||||
else {
|
||||
$attendee_inbox = new WritableCollection(array('path' => $schedule_target->internal_url('schedule-inbox')));
|
||||
if ( ! $attendee_inbox->HavePrivilegeTo('schedule-deliver-invite') ) {
|
||||
$response = '3.8;'.translate('No authority to deliver invitations to user.');
|
||||
}
|
||||
else if ( $attendee_inbox->WriteCalendarMember($schedule_request, $create) === false ) {
|
||||
$response = '5.3;'.translate('No scheduling support for user');
|
||||
}
|
||||
else {
|
||||
$response = '2.0;'.translate('Scheduling invitation delivered successfully');
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$response = '2.0;'.translate('Scheduling invitation delivered successfully');
|
||||
$response = '5.3;'.translate('No scheduling support for user');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$response = '5.3;'.translate('No scheduling support for user');
|
||||
}
|
||||
return '"'.$response.'"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create scheduling requests in the schedule inbox for the
|
||||
* @param vComponent $resource The VEVENT/VTODO/... resource we are scheduling
|
||||
*/
|
||||
function create_scheduling_requests( vCalendar $resource ) {
|
||||
if ( ! is_object($resource) ) {
|
||||
dbg_error_log( 'PUT', 'create_scheduling_requests called with non-object parameter (%s)', gettype($resource) );
|
||||
return;
|
||||
}
|
||||
|
||||
$attendees = $resource->GetAttendees();
|
||||
if ( count($attendees) == 0 ) {
|
||||
dbg_error_log( 'PUT', 'Event has no attendees - no scheduling required.', count($attendees) );
|
||||
return;
|
||||
}
|
||||
|
||||
dbg_error_log( 'PUT', 'Adding to scheduling inbox %d attendees', count($attendees) );
|
||||
$schedule_request = new VCalendar( array('METHOD' => 'REQUEST') );
|
||||
$schedule_request->SetComponents( $resource->GetComponents() );
|
||||
foreach( $attendees AS $attendee ) {
|
||||
$schedule_status = write_scheduling_request( $schedule_request, $attendee->Value(), true );
|
||||
dbg_error_log( 'PUT', 'Status for attendee <%s> set to "%s"', $attendee->Value(), $schedule_status );
|
||||
$attendee->SetParameterValue( 'SCHEDULE-STATUS', $schedule_status );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update scheduling requests in the schedule inbox for the
|
||||
* @param vComponent $resource The VEVENT/VTODO/... resource we are scheduling
|
||||
*/
|
||||
function update_scheduling_requests( vCalendar $resource ) {
|
||||
if ( ! is_object($resource) ) {
|
||||
dbg_error_log( 'PUT', 'update_scheduling_requests called with non-object parameter (%s)', gettype($resource) );
|
||||
return;
|
||||
}
|
||||
|
||||
$attendees = $resource->GetAttendees();
|
||||
if ( count($attendees) == 0 ) {
|
||||
dbg_error_log( 'PUT', 'Event has no attendees - no scheduling required.', count($attendees) );
|
||||
return;
|
||||
}
|
||||
|
||||
dbg_error_log( 'PUT', 'Adding to scheduling inbox %d attendees', count($attendees) );
|
||||
$schedule_request = new VCalendar( array('METHOD' => 'REQUEST') );
|
||||
$schedule_request->SetComponents( $resource->GetComponents() );
|
||||
foreach( $attendees AS $attendee ) {
|
||||
$schedule_status = write_scheduling_request( $schedule_request, $attendee->Value(), false );
|
||||
$schedule_status = '"'.$response.'"';
|
||||
dbg_error_log( 'PUT', 'Status for attendee <%s> set to "%s"', $attendee->Value(), $schedule_status );
|
||||
$attendee->SetParameterValue( 'SCHEDULE-STATUS', $schedule_status );
|
||||
}
|
||||
@ -484,7 +460,7 @@ EOSQL;
|
||||
/** Construct the VCALENDAR data */
|
||||
$vcal = new vCalendar();
|
||||
$vcal->SetComponents($resource);
|
||||
create_scheduling_requests($vcal);
|
||||
do_scheduling_requests($vcal,true);
|
||||
$icalendar = $vcal->Render();
|
||||
|
||||
/** As ever, we mostly deal with the first resource component */
|
||||
@ -623,7 +599,7 @@ EOSQL;
|
||||
write_alarms($dav_id, $first);
|
||||
write_attendees($dav_id, $vcal);
|
||||
|
||||
create_scheduling_requests( $vcal );
|
||||
do_scheduling_requests( $vcal, true );
|
||||
if ( isset($c->skip_bad_event_on_import) && $c->skip_bad_event_on_import ) $qry->Commit();
|
||||
}
|
||||
|
||||
@ -945,7 +921,7 @@ function write_resource( DAVResource $resource, $caldav_data, DAVResource $colle
|
||||
|
||||
if ( !isset($dav_params[':modified']) ) $dav_params[':modified'] = 'now';
|
||||
if ( $put_action_type == 'INSERT' ) {
|
||||
if ( !$collection->IsSchedulingCollection() ) create_scheduling_requests($ic);
|
||||
if ( !$collection->IsSchedulingCollection() ) do_scheduling_requests($ic,true);
|
||||
$sql = 'INSERT INTO caldav_data ( dav_id, user_no, dav_name, dav_etag, caldav_data, caldav_type, logged_user, created, modified, collection_id, weak_etag )
|
||||
VALUES( :dav_id, :user_no, :dav_name, :etag, :dav_data, :caldav_type, :session_user, :created, :modified, :collection_id, :weak_etag )';
|
||||
$dav_params[':collection_id'] = $collection_id;
|
||||
@ -954,7 +930,7 @@ function write_resource( DAVResource $resource, $caldav_data, DAVResource $colle
|
||||
$dav_params[':created'] = (isset($created) && $created != '' ? $created : $dtstamp);
|
||||
}
|
||||
else {
|
||||
if ( !$collection->IsSchedulingCollection() ) update_scheduling_requests($ic);
|
||||
if ( !$collection->IsSchedulingCollection() ) do_scheduling_requests($ic,false);
|
||||
$sql = 'UPDATE caldav_data SET caldav_data=:dav_data, dav_etag=:etag, caldav_type=:caldav_type, logged_user=:session_user,
|
||||
modified=:modified, weak_etag=:weak_etag WHERE dav_id=:dav_id';
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ target_collection: >11<
|
||||
target_resource_i: >NULL<
|
||||
ticket_owner: >1003<
|
||||
|
||||
bind_id: >1624<
|
||||
bind_id: >1628<
|
||||
bind_owner: >1<
|
||||
bound_source_id: >12<
|
||||
dav_displayname: >user3 home<
|
||||
|
||||
@ -2,7 +2,7 @@ HTTP/1.1 200 OK
|
||||
Date: Dow, 01 Jan 2000 00:00:00 GMT
|
||||
DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule
|
||||
DAV: extended-mkcol, calendar-proxy, bind, addressbook, calendar-auto-schedule
|
||||
Content-Length: 20351
|
||||
Content-Length: 21247
|
||||
Etag: "ae93907cb03bc025b8e733eb61f3a09e"
|
||||
Content-Type: text/calendar; charset="utf-8"
|
||||
|
||||
@ -380,6 +380,31 @@ X-MOZ-SEND-INVITATIONS:TRUE
|
||||
SEQUENCE:1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
CREATED:20100319T103247Z
|
||||
LAST-MODIFIED:20100319T105620Z
|
||||
DTSTAMP:20100319T105620Z
|
||||
UID:70399cd7-50a4-4be4-a665-af593e19a7fd
|
||||
SUMMARY:An invited event. Black tie with pink polka dots is essential.
|
||||
Do not bring a leopard. Any leopards which do attend will be forcibly
|
||||
chained to a nearby fence.
|
||||
ORGANIZER;RSVP=TRUE;PARTSTAT=ACCEPTED;ROLE=CHAIR:mailto:user1@example.ne
|
||||
t
|
||||
ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:mailto:use
|
||||
r2@example.net
|
||||
ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:mailto:use
|
||||
r3@example.net
|
||||
ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:mailto:use
|
||||
r4@example.net
|
||||
ATTENDEE;RSVP=TRUE;PARTSTAT=NEEDS-ACTION;ROLE=REQ-PARTICIPANT:mailto:use
|
||||
r5@example.net
|
||||
DTSTART:20100322T160000
|
||||
DTEND:20100322T170000
|
||||
X-MOZ-GENERATION:3
|
||||
TRANSP:OPAQUE
|
||||
X-MOZ-SEND-INVITATIONS:TRUE
|
||||
SEQUENCE:1
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
LAST-MODIFIED:20100125T214235Z
|
||||
SEQUENCE:1
|
||||
UID:73d1f980-ec28-012c-11f9-002421a2359e
|
||||
|
||||
@ -2,8 +2,8 @@ HTTP/1.1 207 Multi-Status
|
||||
Date: Dow, 01 Jan 2000 00:00:00 GMT
|
||||
DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule
|
||||
DAV: extended-mkcol, calendar-proxy, bind, addressbook, calendar-auto-schedule
|
||||
ETag: "669141e7081e1e14a6bef5b2b6327659"
|
||||
Content-Length: 2040
|
||||
ETag: "0d70494d992ba29a4785b464a6325784"
|
||||
Content-Length: 2286
|
||||
Content-Type: text/xml; charset="utf-8"
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
@ -80,5 +80,14 @@ Content-Type: text/xml; charset="utf-8"
|
||||
<status>HTTP/1.1 200 OK</status>
|
||||
</propstat>
|
||||
</response>
|
||||
<response>
|
||||
<href>/caldav.php/user2/home/70399cd7-50a4-4be4-a665-af593e19a7fd.ics</href>
|
||||
<propstat>
|
||||
<prop>
|
||||
<getetag>"baad41c9f24bd1ecbdde6e58882df9b7"</getetag>
|
||||
</prop>
|
||||
<status>HTTP/1.1 200 OK</status>
|
||||
</propstat>
|
||||
</response>
|
||||
<sync-token>5</sync-token>
|
||||
</multistatus>
|
||||
|
||||
@ -35,7 +35,7 @@ Content-Type: text/plain; charset="utf-8"
|
||||
length: >8<
|
||||
parent_container: >/user4/base/<
|
||||
|
||||
bind_id: >1625<
|
||||
bind_id: >1629<
|
||||
bound_source_id: >1601<
|
||||
dav_displayname: >A normal collection<
|
||||
dav_name: >/user4/boundbase/<
|
||||
|
||||
@ -112,7 +112,7 @@
|
||||
<prop>
|
||||
<displayname>newcalendar</displayname>
|
||||
<resource-id>
|
||||
<href>/caldav.php/.resources/1614</href>
|
||||
<href>/caldav.php/.resources/1618</href>
|
||||
</resource-id>
|
||||
<parent-set>
|
||||
<parent>
|
||||
|
||||
@ -125,7 +125,7 @@
|
||||
<prop>
|
||||
<displayname>newcalendar</displayname>
|
||||
<resource-id>
|
||||
<href>/caldav.php/.resources/1614</href>
|
||||
<href>/caldav.php/.resources/1618</href>
|
||||
</resource-id>
|
||||
<parent-set>
|
||||
<parent>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
setval
|
||||
--------
|
||||
1625
|
||||
1629
|
||||
(1 row)
|
||||
|
||||
setval
|
||||
|
||||
@ -5,12 +5,10 @@ Date: Dow, 01 Jan 2000 00:00:00 GMT
|
||||
DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule
|
||||
DAV: extended-mkcol, calendar-proxy, bind, addressbook, calendar-auto-schedule
|
||||
ETag: "e69b6d5b70189b96126c8993bcf1648a"
|
||||
Content-Length: 112
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
|
||||
|
||||
Notice: Undefined variable: log_action in /home/karora/projects/davical/inc/WritableCollection.php on line 259
|
||||
|
||||
caldav_data: >BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
PRODID:-//Apple Inc.//iCal 3.0//EN
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
setval
|
||||
--------
|
||||
1637
|
||||
1641
|
||||
(1 row)
|
||||
|
||||
setval
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user