Object ::caldav::calendars (public)
::nx::Object ::caldav::calendars
Defined in packages/xotcl-core/tcl/01-debug-procs.tcl
The class "calendars" implements the interface to the database structures.
- ::caldav::calendars get_cal_item_from_uid ?-calendar_ids /integer .../? /uid/
- ::caldav::calendars timezone
- ::caldav::calendars communityCalendarClause /user_id/
- ::caldav::calendars get_calendar_and_cal_item_from_uid ?-calendar_ids /integer .../? /uid/
- ::caldav::calendars alwaysQueriedClause /user_id/
- ::caldav::calendars get_calitems ?-user_id /integer/? ?-start_date /value/? ?-end_date /value/? ?-calendar_ids /integer .../?
- ::caldav::calendars header ?-calendar_name /value/?
- ::caldav::calendars parse /text/
- ::caldav::calendars alwaysQueriedCalendars ?-with_sync_calendar /boolean/? /user_id/
- ::caldav::calendars calendar_clause ?-calendar_ids /integer .../? ?-user_id /integer/? ?-attr /value/?
- ::caldav::calendars format_recurrence ?-recurrence_id /integer/?
- ::caldav::calendars footer
- Testcases:
- No testcase defined.
Source code: :object method debug {msg} { ns_log Debug(caldav) "[uplevel current proc]: $msg" } # TODO move get_sync_calendar here # :public object method format_recurrence { {-recurrence_id:integer,0..1} } { # Return the recurrence specification in form of a formatted # ical RRULE. @param recurrence_id is the unique id of the # recurrence item. if {$recurrence_id eq ""} { return "" } #ns_log notice "recurrence_id $recurrence_id" set recur_rule "RRULE:FREQ=" ::xo::dc 1row -prepare integer select_recurrence { select recurrence_id, recurrences.interval_type, interval_name, every_nth_interval, days_of_week, recur_until from recurrences, recurrence_interval_types where recurrence_id= :recurrence_id and recurrences.interval_type = recurrence_interval_types.interval_type } switch -glob $interval_name { day { append recur_rule "DAILY" } week { append recur_rule "WEEKLY" } *month* { append recur_rule "MONTHLY"} year { append recur_rule "YEARLY"} } if { $interval_name eq "week" && $days_of_week ne "" } { #DRB: Standard indicates ordinal week days are OK, but Outlook #only takes two-letter abbreviation form. set week_list [list "SU" "MO" "TU" "WE" "TH" "FR" "SA" "SU"] set rec_list [list] foreach day [split $days_of_week " "] { lappend rec_list [lindex $week_list $day] } append recur_rule ";BYDAY=" [join $rec_list ,] } if {$every_nth_interval ne ""} { append recur_rule ";INTERVAL=$every_nth_interval" } if {$recur_until ne ""} { set stamp [string range $recur_until 0 18] append recur_rule ";UNTIL=" [xo::ical tcl_time_to_utc $stamp] } #ns_log notice "recur_rule $recur_rule" return [::xo::ical reflow_content_line $recur_rule]\r\n } :public object method get_cal_item_from_uid { {-calendar_ids:integer,0..n} uid } { # @return for a uid the cal_item_id(s?) # @param uid unique id of an calendar item # # GN TODO: # # - document, why and how the or test "e.activity_id = :uid" is # needed this looks like a hack, since the UID can be modified # by a calendar client, we can't assume that this is the same # as some OpenACS id. # # - when the uid refers to a recurrence item, multiple # cal_item_ids are returned. (a) is this needed (maybe limit # 1 is sufficient)? (b) is this handled everywhere # correctly? (c) if needed, name should be change to # get_cal_items_from_uid # # - HOW ABOUT using activity_id instead of the cal_item_id... such as get_activity_from_uid # # - probably base on get_calendar_and_cal_item_from_uid # # if {[llength $calendar_ids] > 1} { set calclause "in ( [ns_dbquotelist $calendar_ids] )" } elseif {[llength $calendar_ids] eq 0} { return 0 } else { set calclause "= :calendar_ids" } set e_clause [expr {[nsf::is integer $uid] ? " or e.activity_id = :uid" : ""}] return [::xo::dc list get_cal_item_from_uid [subst { select cal_item_id from cal_items c, acs_events e left outer join cal_uids u on u.on_which_activity = e.activity_id where c.cal_item_id = e.event_id and ( u.cal_uid = :uid $e_clause ) and c.on_which_calendar $calclause order by 1 desc }]] } :public object method get_calendar_and_cal_item_from_uid { {-calendar_ids:integer,0..n} uid } { # @return for a uid the cal_item_id(s?) # @param uid unique id of an calendar item # # GN TODO: # # - see above... get_cal_item_from_uid # # The following query is tricky, since it avoids # an error "invalid input syntax for integer" on uids like # # 23009F17-383F-4FBD-92D4-AB0F27CF7326 # # needs probably work for Oracle. # return [::xo::dc list_of_lists query_calendar_and_cal_item { select c.on_which_calendar, c.cal_item_id from acs_events e, cal_items c where e.activity_id in ( select CASE WHEN :uid !~ '^[0-9]+$' THEN NULL ELSE :uid ::text::integer END union (select on_which_activity from cal_uids where cal_uid = :uid) ) and c.cal_item_id = e.event_id order by 2 desc limit 1 }] # set e_clause [expr {[nsf::is integer $uid] ? " or e.activity_id = :uid" : ""}] # # - we could pass-in a calendar-clause, would save a query in # the PUT case #if {[llength $calendar_ids] > 1} { # set calclause "in ( [ns_dbquotelist $calendar_ids] )" #} elseif {[llength $calendar_ids] eq 0} { # return 0 #} else { # set calclause "= :calendar_ids" #} # return [::xo::dc list query_calendar_and_cal_item [subst { # select c.on_which_calendar, cal_item_id # from cal_items c, acs_events e # left outer join cal_uids u on u.on_which_activity = e.activity_id # where c.cal_item_id = e.event_id # and ( u.cal_uid = :uid $e_clause ) # and c.on_which_calendar $calclause # order by 2 desc}]] } :public object method alwaysQueriedCalendars { {-with_sync_calendar:boolean true} user_id:integer } { # # @return the calendar_ids, which should be always returned # lappend calendar_ids {*}[::caldav::get_public_calendars] if {$with_sync_calendar} { lappend calendar_ids [::caldav::get_sync_calendar -user_id $user_id] } return $calendar_ids } :public object method alwaysQueriedClause { user_id:integer } { # # @return SQL clause which is always queried # set calendar_ids [:alwaysQueriedCalendars $user_id] if {[llength $calendar_ids] > 0} { set values [::xo::db::list_to_values $calendar_ids integer] set result [list "select calendar_id from $values as values(calendar_id)"] } else { set result {} } return $result } :public object method communityCalendarClause { user_id:integer } { # # Get calendars from communities, when DotLRN is active. # if {[info commands ::dotlrn_calendar::my_package_key] ne ""} { set result [list " WITH communities AS ( select distinct dcc.community_id from dotlrn_communities_core dcc inner join dotlrn_member_rels_approved dma on dcc.community_id = dma.community_id and dma.user_id = $user_id and dcc.archived_p = 'f' ) select calendar_id from communities m, calendars c join dotlrn_community_applets a on (a.package_id = c.package_id) join dotlrn_applets ap on (ap.applet_id = a.applet_id) where ap.package_key = 'dotlrn-calendar' and a.community_id = m.community_id "] } else { set result {} } return $result } :public object method calendar_clause { {-calendar_ids:integer,0..n ""} {-user_id:integer} {-attr c.on_which_calendar} } { # # When calendar_ids are empty, user_id has to be specified # if {$calendar_ids eq ""} { lappend clauses {*}[:communityCalendarClause $user_id] {*}[:alwaysQueriedClause $user_id] set clause [subst { and $attr in ([join $clauses " union "]) }] } elseif {[llength $calendar_ids] == 1} { set clause [subst {and $attr = :calendar_ids}] } else { set clause [subst {and $attr in ( [ns_dbquotelist $calendar_ids] )}] } :debug calendar_clause=$clause-calendar_ids=$calendar_ids return $clause } # # API for selecting calendar items # :public object method get_calitems { {-user_id:integer ""} {-start_date ""} {-end_date ""} {-calendar_ids:integer,0..n ""} } { # # Get feed of calendar items for a given user. # # @return list set of calendar item objects :debug "get_calitems [current args]" if {$start_date ne "" && $end_date ne ""} { set time_limitation_clause [subst { and start_date between to_timestamp('$start_date','YYYY-MM-DD HH24:MI:SS') and to_timestamp('$end_date', 'YYYY-MM-DD HH24:MI:SS') }] } else { set time_limitation_clause "" } set eventlist {} set recurrences {} # # Note that we can have items without a entry in cal_uids for # these we will use the activity_id as uid calendars of # communities, personal calendars, and public calendars in the # same package as the personal calendar- # foreach item [::xo::dc list_of_lists cal_items [subst { select md5(last_modified::text) as etag, coalesce(cal_uid, e.activity_id::varchar), ical_vars, on_which_calendar, c.item_type_id, to_char(start_date, 'YYYY-MM-DD HH24:MI:SS'), to_char(end_date, 'YYYY-MM-DD HH24:MI:SS'), coalesce(e.name, a.name), coalesce(e.description, a.description), c.cal_item_id, recurrence_id, creation_date, last_modified from acs_objects ao, acs_events e left outer join cal_uids u on u.on_which_activity = e.activity_id, acs_activities a, timespans s, time_intervals t, cal_items c where e.event_id = ao.object_id and a.activity_id = e.activity_id and c.cal_item_id = e.event_id and e.timespan_id = s.timespan_id and s.interval_id = t.interval_id $time_limitation_clause [:calendar_clause -calendar_ids $calendar_ids -user_id $user_id] order by start_date asc }]] { lassign $item etag cal_uid ical_vars calendar_id item_type start_date end_date name description cal_item_id recurrence_id creation_date last_modified #ns_log notice "get_calitems: item $cal_item_id calendar $calendar_id" "we got an recurrence <$recurrence_id>" if {$recurrence_id ne "" && $recurrence_id in $recurrences} { # # Don't report calendar items with recurrence multiple # times. # continue } set caldavItem [::caldav::calitem new -uid $cal_uid -ical_vars $ical_vars -etag $etag -creation_date $creation_date -last_modified $last_modified -dtstart $start_date -is_day_item [dt_no_time_p -start_time $start_date -end_time $end_date] -formatted_recurrences [:format_recurrence -recurrence_id $recurrence_id] -dtend $end_date -summary $name -description $description ] $caldavItem destroy_on_cleanup lappend eventlist $caldavItem lappend recurrences $recurrence_id } return $eventlist }XQL Not present: Generic, PostgreSQL, Oracle