From fe443bf2e64f6ce21c08a7890f9e418548df4c22 Mon Sep 17 00:00:00 2001 From: Jamie McClymont Date: Tue, 8 Jan 2019 13:05:34 +1300 Subject: [PATCH] Update instance range columns when a collection's timezone changes TODO: Handle the case where it is updated through the web UI --- inc/auth-functions.php | 3 +++ inc/caldav-PROPPATCH.php | 4 +++ inc/instance_range.php | 55 ++++++++++++++++++++++++++++++++++++++ inc/ui/collection-edit.php | 14 ++++++++++ 4 files changed, 76 insertions(+) create mode 100644 inc/instance_range.php diff --git a/inc/auth-functions.php b/inc/auth-functions.php index 6ec757d3..e97743f6 100644 --- a/inc/auth-functions.php +++ b/inc/auth-functions.php @@ -231,6 +231,9 @@ function UpdateCollectionTimezones( $username, $new_timezone=null ) { if ( empty($new_timezone) ) return; $qry = new AwlQuery('UPDATE collection SET timezone=? WHERE dav_name LIKE ? AND is_calendar', '/'.$username.'/%', $new_timezone); $qry->Exec(); + + require_once("instance_range.php"); + update_instance_ranges($dav_resource->dav_name()); } /** diff --git a/inc/caldav-PROPPATCH.php b/inc/caldav-PROPPATCH.php index d4b94ff8..7bda9408 100644 --- a/inc/caldav-PROPPATCH.php +++ b/inc/caldav-PROPPATCH.php @@ -275,6 +275,8 @@ foreach( $setprops AS $k => $setting ) { $qry->QDo('UPDATE collection SET timezone = :tzid WHERE dav_name = :dav_name', array( ':tzid' => $tzid, ':dav_name' => $dav_resource->dav_name()) ); + require_once("instance_range.php"); + update_instance_ranges($dav_resource->dav_name()); } else { add_failure('set', $tag, 'HTTP/1.1 409 Conflict', translate("calendar-timezone property is only valid for a calendar.")); @@ -389,6 +391,8 @@ foreach( $rmprops AS $k => $setting ) { case 'urn:ietf:params:xml:ns:caldav:calendar-timezone': if ( $dav_resource->IsCollection() && $dav_resource->IsCalendar() && ! $dav_resource->IsBinding() ) { $qry->QDo('UPDATE collection SET timezone = NULL WHERE dav_name = :dav_name', array( ':dav_name' => $dav_resource->dav_name()) ); + require_once("instance_range.php"); + update_instance_ranges($dav_resource->dav_name()); } else { add_failure('rm', $tag, 'HTTP/1.1 403 Forbidden', diff --git a/inc/instance_range.php b/inc/instance_range.php new file mode 100644 index 00000000..c1cdee17 --- /dev/null +++ b/inc/instance_range.php @@ -0,0 +1,55 @@ +TransactionState() == 1); + if ( ! $in_transaction ) $qry->Begin(); + + $qry->QDo( + "SELECT d.dav_id, c.collection_id, d.caldav_data, c.timezone, i.first_instance_start, i.last_instance_end + FROM caldav_data d + INNER JOIN collection c ON d.collection_id = c.collection_id + INNER JOIN calendar_item i ON d.collection_id = i.collection_id AND d.dav_id = i.dav_id + WHERE c.dav_name = :dav_name", + [":dav_name" => $collection_dav_name] + ); + + while( $row = $qry->Fetch() ) { + $range = getVCalendarRange(new vCalendar($row->caldav_data), $row->timezone); + + $new_start = isset($range->from) ? $range->from->UTC() : null; + $new_end = isset($range->until) ? $range->until->UTC() : null; + + if ($new_start != $row->first_instance_start || $new_end != $row->last_instance_end) { + $inner_qry = new AwlQuery( + "UPDATE calendar_item + SET first_instance_start = :first_instance_start, + last_instance_end = :last_instance_end + WHERE collection_id = :collection_id AND dav_id = :dav_id", + [ + ":dav_id" => $row->dav_id, + ":collection_id" => $row->collection_id, + + ":first_instance_start" => $new_start, + ":last_instance_end" => $new_end + ] + ); + $inner_qry->Exec('UpdateInstanceRange',__LINE__,__FILE__); + } + } + + if ( ! $in_transaction ) $qry->Commit(); +} + +?> diff --git a/inc/ui/collection-edit.php b/inc/ui/collection-edit.php index 8c1d8401..4fa778c9 100644 --- a/inc/ui/collection-edit.php +++ b/inc/ui/collection-edit.php @@ -91,7 +91,14 @@ if ( $can_write_collection && $editor->IsSubmit() ) { } else { $c->messages[] = i18n("Updating Collection."); + + // We need to know whether to update_instance_ranges, which is an expensive + // operation we should only do if the collection timezone has been updated + $tzqry = new AwlQuery( "SELECT timezone FROM collection WHERE collection_id=:id", [ ":id" => $id ] ); + $tzqry->Exec('collection-edit',__LINE__,__FILE__); + $old_tz = $tzqry->Fetch()->timezone; } + if ( !$editor->Write() ) { $c->messages[] = i18n("Failed to write collection."); if ( $id > 0 ) $editor->GetRecord(); @@ -121,6 +128,13 @@ if ( $can_write_collection && $editor->IsSubmit() ) { $c->messages[] = i18n('The file is not UTF-8 encoded, please check the error for more details.'); } } + + if ($editor->IsCreate() || $old_tz != $_POST['timezone']) { + dbg_error_log('collection-edit', 'Need to update instance ranges, this will take a while...'); + require_once("instance_range.php"); + update_instance_ranges($editor->Value('dav_name')); + } + // Uncache anything to do with the collection $cache = getCacheInstance(); $cache->delete( 'collection-'.$editor->Value('dav_name'), null );