CalDAV: properly implement the CTag feature
Instead of using the ETag (which looks at the modification time of the base.calendar object), aggregate over the contained calendar entries to find their maximum modification. bzr revid: p_christ@hol.gr-20101012104037-847evso9mryqom5f
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user