Add items to attendee's calendars as well as to their inboxes on PUT.

This commit is contained in:
Andrew McMillan 2011-09-10 00:17:27 +12:00
parent bdb360f082
commit 4f01fe0a17
11 changed files with 131 additions and 105 deletions

View File

@ -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;
}

View File

@ -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';
}

View File

@ -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<

View File

@ -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

View File

@ -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>

View File

@ -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/<

View File

@ -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>

View File

@ -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>

View File

@ -1,6 +1,6 @@
setval
--------
1625
1629
(1 row)
setval

View File

@ -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

View File

@ -1,6 +1,6 @@
setval
--------
1637
1641
(1 row)
setval