diff --git a/addons/caldav/caldav_node.py b/addons/caldav/caldav_node.py index 510e43eabd0..52da451b567 100644 --- a/addons/caldav/caldav_node.py +++ b/addons/caldav/caldav_node.py @@ -21,33 +21,14 @@ import time from document_webdav import nodes +from document.nodes import _str2time import logging import StringIO +from tools.dict_tools import dict_merge, dict_merge2 + # TODO: implement DAV-aware errors, inherit from IOError -def dict_merge(*dicts): - """ Return a dict with all values of dicts - """ - res = {} - for d in dicts: - res.update(d) - return res - -def dict_merge2(*dicts): - """ Return a dict with all values of dicts. - If some key appears twice and contains iterable objects, the values - are merged (instead of overwritten). - """ - res = {} - for d in dicts: - for k in d.keys(): - if k in res and isinstance(res[k], (list, tuple)): - res[k] = res[k] + d[k] - else: - res[k] = d[k] - return res - # Assuming that we have set global properties right, we mark *all* # directories as having calendar-access. nodes.node_dir.http_options = dict_merge2(nodes.node_dir.http_options, @@ -186,10 +167,18 @@ class node_calendar(nodes.node_class): self.content_length = 0 self.displayname = calendar.name self.cal_type = calendar.type + # TODO owner + def _get_dav_getctag(self, cr): - result = self._get_ttag(cr) + ':' + str(time.time()) - return str(result) + dirobj = self.context._dirobj + uid = self.context.uid + ctx = self.context.context.copy() + ctx.update(self.dctx) + + bc_obj = dirobj.pool.get('basic.calendar') + res = bc_obj.get_cal_max_modified(cr, uid, [self.calendar_id], self, domain=[], context=ctx) + return _str2time(res) def _get_dav_user_state(self, cr): #TODO @@ -295,11 +284,9 @@ class node_calendar(nodes.node_class): if not domain: domain = [] - fil_obj = dirobj.pool.get('basic.calendar') - ids = fil_obj.search(cr, uid, domain) - res = [] - if self.calendar_id in ids: - res = fil_obj.get_calendar_objects(cr, uid, [self.calendar_id], self, domain=where, context=ctx) + bc_obj = dirobj.pool.get('basic.calendar') + # we /could/ be supplying an invalid calendar id to bc_obj, it has to check + res = bc_obj.get_calendar_objects(cr, uid, [self.calendar_id], self, domain=where, context=ctx) return res def create_child(self, cr, path, data): diff --git a/addons/caldav/calendar.py b/addons/caldav/calendar.py index 2f7d978b5a6..2133e3be293 100644 --- a/addons/caldav/calendar.py +++ b/addons/caldav/calendar.py @@ -552,6 +552,33 @@ class CalDAV(object): self.ical_reset('value') return res +if True: # we need this indentation level ;) + + def get_last_modified(self, cr, user, args, context=None, access_rights_uid=None): + """Return the last modification date of objects in 'domain' + This function has similar semantics to orm.search(), apart from the + limit, offset and order arguments, which make no sense here. + It is useful when we want to find if the table (aka set of records) + has any modifications we should update at the client. + """ + if context is None: + context = {} + self.pool.get('ir.model.access').check(cr, access_rights_uid or user, self._name, 'read', context=context) + + query = self._where_calc(cr, user, args, context=context) + self._apply_ir_rules(cr, user, query, 'read', context=context) + from_clause, where_clause, where_clause_params = query.get_sql() + + where_str = where_clause and (" WHERE %s" % where_clause) or '' + + cr.execute('SELECT MAX(COALESCE("%s".write_date, "%s".create_date)) FROM ' % (self._table, self._table) + + from_clause + where_str , + where_clause_params, + debug=self._debug) + res = cr.fetchall() + return res[0][0] + + class Calendar(CalDAV, osv.osv): _name = 'basic.calendar' _calname = 'calendar' @@ -610,6 +637,32 @@ class Calendar(CalDAV, osv.osv): node = res_node_calendar('%s.ics' %data.id, parent, ctx, data, line.object_id.model, data.id) res.append(node) return res + + + def get_cal_max_modified(self, cr, uid, ids, parent=None, domain=None, context=None): + if not context: + context = {} + if not domain: + domain = [] + res = None + ctx_res_id = context.get('res_id', None) + ctx_model = context.get('model', None) + for cal in self.browse(cr, uid, ids): + for line in cal.line_ids: + if ctx_model and ctx_model != line.object_id.model: + continue + if line.name in ('valarm', 'attendee'): + continue + line_domain = eval(line.domain or '[]', context) + line_domain += domain + if ctx_res_id: + line_domain += [('id','=',ctx_res_id)] + mod_obj = self.pool.get(line.object_id.model) + max_data = get_last_modified(mod_obj, cr, uid, line_domain, context=context) + if res and res > max_data: + continue + res = max_data + return res def export_cal(self, cr, uid, ids, vobj='vevent', context=None): """ Export Calendar