837 lines
33 KiB
Python
837 lines
33 KiB
Python
# -*- coding: utf-8 -*-
|
|
##############################################################################
|
|
#
|
|
# OpenERP, Open Source Management Solution
|
|
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
# License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
##############################################################################
|
|
|
|
import base64
|
|
|
|
from osv import osv, fields
|
|
from osv.orm import except_orm
|
|
import urlparse
|
|
import pooler
|
|
from tools.safe_eval import safe_eval
|
|
|
|
import os
|
|
import time
|
|
|
|
#
|
|
# An object that represent an uri
|
|
# path: the uri of the object
|
|
# content: the Content it belongs to (_print.pdf)
|
|
# type: content or collection
|
|
# content: objct = res.partner
|
|
# collection: object = directory, object2 = res.partner
|
|
# file: objct = ir.attachement
|
|
# root: if we are at the first directory of a ressource
|
|
#
|
|
|
|
def get_node_context(cr, uid, context):
|
|
return node_context(cr,uid,context)
|
|
|
|
class node_context(object):
|
|
""" This is the root node, representing access to some particular
|
|
context """
|
|
cached_roots = {}
|
|
|
|
def __init__(self, cr, uid, context=None):
|
|
# we don't cache the cr!
|
|
self.dbname = cr.dbname
|
|
self.uid = uid
|
|
self.context = context
|
|
self._dirobj = pooler.get_pool(cr.dbname).get('document.directory')
|
|
assert self._dirobj
|
|
self.rootdir = self._dirobj._get_root_directory(cr,uid,context)
|
|
|
|
def get_uri(self, cr, uri):
|
|
""" Although this fn passes back to doc.dir, it is needed since
|
|
it is a potential caching point """
|
|
(ndir, duri) = self._dirobj._locate_child(cr,self.uid, self.rootdir,uri, None, self)
|
|
while duri:
|
|
ndir = ndir.child(cr, duri[0])
|
|
if not ndir:
|
|
return False
|
|
duri = duri[1:]
|
|
return ndir
|
|
|
|
|
|
class node_database():
|
|
""" A node representing the database directory
|
|
Useless?
|
|
"""
|
|
def __init__(self,ncontext):
|
|
self.nctx = ncontext
|
|
|
|
|
|
|
|
|
|
class node_class(object):
|
|
""" this is a superclass for our inodes
|
|
It is an API for all code that wants to access the document files.
|
|
Nodes have attributes which contain usual file properties
|
|
"""
|
|
our_type = 'baseclass'
|
|
def __init__(self, path, parent, context):
|
|
assert isinstance(context,node_context)
|
|
assert (not parent ) or isinstance(parent,node_class)
|
|
self.path = path
|
|
self.context = context
|
|
self.type=self.our_type
|
|
self.parent = parent
|
|
self.mimetype = 'application/octet-stream'
|
|
self.create_date = None
|
|
self.write_date = None
|
|
self.content_length = 0
|
|
# dynamic context:
|
|
self.dctx = {}
|
|
if parent:
|
|
self.dctx = parent.dctx.copy()
|
|
self.displayname = 'Object'
|
|
|
|
def full_path(self):
|
|
""" Return the components of the full path for some
|
|
node.
|
|
The returned list only contains the names of nodes.
|
|
"""
|
|
if self.parent:
|
|
s = self.parent.full_path()
|
|
else:
|
|
s = []
|
|
if isinstance(self.path,list):
|
|
s+=self.path
|
|
else:
|
|
s.append(self.path)
|
|
return s #map(lambda x: '/' +x, s)
|
|
|
|
def children(self, cr):
|
|
print "node_class.children()"
|
|
return [] #stub
|
|
|
|
def child(self,cr, name):
|
|
print "node_class.child()"
|
|
return None
|
|
|
|
def path_get(self):
|
|
print "node_class.path_get()"
|
|
return False
|
|
|
|
def get_data(self,cr):
|
|
raise TypeError('no data for %s'% self.type)
|
|
|
|
def _get_storage(self,cr):
|
|
raise RuntimeError("no storage for base class")
|
|
|
|
def get_etag(self,cr):
|
|
""" Get a tag, unique per object + modification.
|
|
|
|
see. http://tools.ietf.org/html/rfc2616#section-13.3.3 """
|
|
return self._get_ttag(cr) + ':' + self._get_wtag(cr)
|
|
|
|
def _get_wtag(self,cr):
|
|
""" Return the modification time as a unique, compact string """
|
|
if self.write_date:
|
|
wtime = time.mktime(time.strptime(self.write_date,'%Y-%m-%d %H:%M:%S'))
|
|
else: wtime = time.time()
|
|
return str(wtime)
|
|
|
|
def _get_ttag(self,cr):
|
|
""" Get a unique tag for this type/id of object.
|
|
Must be overriden, so that each node is uniquely identified.
|
|
"""
|
|
print "node_class.get_ttag()",self
|
|
raise RuntimeError("get_etag stub()")
|
|
|
|
def get_dav_props(self, cr):
|
|
""" If this class has special behaviour for GroupDAV etc, export
|
|
its capabilities """
|
|
return {}
|
|
|
|
def get_dav_eprop(self,cr,ns,prop):
|
|
return None
|
|
|
|
class node_dir(node_class):
|
|
our_type = 'collection'
|
|
def __init__(self,path, parent, context, dirr, dctx=None):
|
|
super(node_dir,self).__init__(path, parent,context)
|
|
self.dir_id = dirr.id
|
|
#todo: more info from dirr
|
|
self.mimetype = 'application/x-directory'
|
|
# 'httpd/unix-directory'
|
|
self.create_date = dirr.create_date
|
|
self.domain = dirr.domain
|
|
self.res_model = dirr.ressource_type_id and dirr.ressource_type_id.model or False
|
|
# TODO: the write date should be MAX(file.write)..
|
|
self.write_date = dirr.write_date or dirr.create_date
|
|
self.content_length = 0
|
|
if dctx:
|
|
self.dctx.update(dctx)
|
|
dc2 = self.context.context
|
|
dc2.update(self.dctx)
|
|
dc2['dir_id'] = self.dir_id
|
|
self.displayname = dirr.name
|
|
if dirr.dctx_ids:
|
|
for dfld in dirr.dctx_ids:
|
|
try:
|
|
self.dctx['dctx_' + dfld.field] = safe_eval(dfld.expr,dc2)
|
|
except Exception,e:
|
|
print "Cannot eval %s" % dfld.expr
|
|
print e
|
|
pass
|
|
|
|
def children(self,cr):
|
|
return self._child_get(cr) + self._file_get(cr)
|
|
|
|
def child(self,cr, name):
|
|
res = self._child_get(cr,name)
|
|
if res:
|
|
return res[0]
|
|
res = self._file_get(cr,name)
|
|
if res:
|
|
return res[0]
|
|
return None
|
|
|
|
def _file_get(self,cr, nodename=False):
|
|
res = []
|
|
cntobj = self.context._dirobj.pool.get('document.directory.content')
|
|
uid = self.context.uid
|
|
ctx = self.context.context.copy()
|
|
ctx.update(self.dctx)
|
|
where = [('directory_id','=',self.dir_id) ]
|
|
ids = cntobj.search(cr, uid, where, context=ctx)
|
|
for content in cntobj.browse(cr, uid, ids, context=ctx):
|
|
res3 = cntobj._file_get(cr, self, nodename, content)
|
|
if res3:
|
|
res.extend(res3)
|
|
|
|
return res
|
|
|
|
def get_dav_props(self, cr):
|
|
res = {}
|
|
cntobj = self.context._dirobj.pool.get('document.directory.content')
|
|
uid = self.context.uid
|
|
ctx = self.context.context.copy()
|
|
ctx.update(self.dctx)
|
|
where = [('directory_id','=',self.dir_id) ]
|
|
ids = cntobj.search(cr,uid,where,context=ctx)
|
|
for content in cntobj.browse(cr,uid,ids,context=ctx):
|
|
if content.extension == '.ics': # FIXME: call the content class!
|
|
res['http://groupdav.org/'] = ('resourcetype',)
|
|
break
|
|
return res
|
|
|
|
def get_dav_eprop(self,cr,ns,prop):
|
|
if ns != 'http://groupdav.org/' or prop != 'resourcetype':
|
|
print "Who asked for %s:%s?" % (ns,prop)
|
|
return None
|
|
res = {}
|
|
cntobj = self.context._dirobj.pool.get('document.directory.content')
|
|
uid = self.context.uid
|
|
ctx = self.context.context.copy()
|
|
ctx.update(self.dctx)
|
|
where = [('directory_id','=',self.dir_id) ]
|
|
ids = cntobj.search(cr,uid,where,context=ctx)
|
|
for content in cntobj.browse(cr,uid,ids,context=ctx):
|
|
if content.extension == '.ics': # FIXME: call the content class!
|
|
return ('vevent-collection','http://groupdav.org/')
|
|
return None
|
|
|
|
def _child_get(self,cr,name = None):
|
|
dirobj = self.context._dirobj
|
|
uid = self.context.uid
|
|
ctx = self.context.context.copy()
|
|
ctx.update(self.dctx)
|
|
where = [('parent_id','=',self.dir_id) ]
|
|
if name:
|
|
where.append(('name','=',name))
|
|
|
|
ids = dirobj.search(cr, uid, where + [('ressource_parent_type_id','=',False)],context=ctx)
|
|
res = []
|
|
if ids:
|
|
for dirr in dirobj.browse(cr,uid,ids,context=ctx):
|
|
if dirr.type == 'directory':
|
|
res.append(node_dir(dirr.name,self,self.context,dirr))
|
|
elif dirr.type == 'ressource':
|
|
res.append(node_res_dir(dirr.name,self,self.context,dirr))
|
|
|
|
fil_obj=dirobj.pool.get('ir.attachment')
|
|
#where2 = where # + [('res_model', '=', None)]
|
|
ids = fil_obj.search(cr,uid,where,context=ctx)
|
|
if ids:
|
|
for fil in fil_obj.browse(cr,uid,ids,context=ctx):
|
|
res.append(node_file(fil.name,self,self.context,fil))
|
|
|
|
return res
|
|
|
|
def create_child(self,cr,path,data):
|
|
""" API function to create a child file object and node
|
|
Return the node_* created
|
|
"""
|
|
dirobj = self.context._dirobj
|
|
uid = self.context.uid
|
|
ctx = self.context.context.copy()
|
|
ctx.update(self.dctx)
|
|
fil_obj=dirobj.pool.get('ir.attachment')
|
|
val = {
|
|
'name': path,
|
|
'datas_fname': path,
|
|
'parent_id': self.dir_id,
|
|
# Datas are not set here
|
|
}
|
|
|
|
fil_id = fil_obj.create(cr,uid, val, context=ctx)
|
|
fil = fil_obj.browse(cr,uid,fil_id,context=ctx)
|
|
fnode = node_file(path,self,self.context,fil)
|
|
fnode.set_data(cr,data,fil)
|
|
return fnode
|
|
|
|
def _get_ttag(self,cr):
|
|
return 'dir-%d' % self.dir_id
|
|
|
|
class node_res_dir(node_class):
|
|
""" A special sibling to node_dir, which does only contain dynamically
|
|
created folders foreach resource in the foreign model.
|
|
All folders should be of type node_res_obj and merely behave like
|
|
node_dirs (with limited domain).
|
|
"""
|
|
our_type = 'collection'
|
|
def __init__(self,path, parent, context, dirr, dctx=None ):
|
|
super(node_res_dir,self).__init__(path, parent,context)
|
|
self.dir_id = dirr.id
|
|
#todo: more info from dirr
|
|
self.mimetype = 'application/x-directory'
|
|
# 'httpd/unix-directory'
|
|
self.create_date = dirr.create_date
|
|
# TODO: the write date should be MAX(file.write)..
|
|
self.write_date = dirr.write_date or dirr.create_date
|
|
self.content_length = 0
|
|
self.res_model = dirr.ressource_type_id and dirr.ressource_type_id.model or False
|
|
self.resm_id = dirr.ressource_id
|
|
self.namefield = dirr.resource_field or 'name'
|
|
self.displayname = dirr.name
|
|
# Important: the domain is evaluated using the *parent* dctx!
|
|
self.domain = dirr.domain
|
|
self.ressource_tree = dirr.ressource_tree
|
|
# and then, we add our own vars in the dctx:
|
|
if dctx:
|
|
self.dctx.update(dctx)
|
|
|
|
# and then, we prepare a dctx dict, for deferred evaluation:
|
|
self.dctx_dict = {}
|
|
for dfld in dirr.dctx_ids:
|
|
self.dctx_dict['dctx_' + dfld.field] = dfld.expr
|
|
|
|
def children(self,cr):
|
|
return self._child_get(cr)
|
|
|
|
def child(self,cr, name):
|
|
res = self._child_get(cr,name)
|
|
if res:
|
|
return res[0]
|
|
return None
|
|
|
|
def _child_get(self,cr,name = None):
|
|
""" return virtual children of resource, based on the
|
|
foreign object.
|
|
|
|
Note that many objects use NULL for a name, so we should
|
|
better call the name_search(),name_get() set of methods
|
|
"""
|
|
obj = self.context._dirobj.pool.get(self.res_model)
|
|
if not obj:
|
|
print "couldn't find model", self.res_model
|
|
return []
|
|
dirobj = self.context._dirobj
|
|
uid = self.context.uid
|
|
ctx = self.context.context.copy()
|
|
ctx.update(self.dctx)
|
|
where = []
|
|
if self.domain:
|
|
where += safe_eval(self.domain, self.dctx)
|
|
if self.resm_id:
|
|
where.append(('id','=',self.resm_id))
|
|
|
|
if name:
|
|
where.append((self.namefield,'=',name))
|
|
|
|
# print "Where clause for %s" % self.res_model, where
|
|
if self.ressource_tree:
|
|
object2 = False
|
|
if self.resm_id:
|
|
object2 = dirobj.pool.get(self.res_model).browse(cr, uid, self.resm_id) or False
|
|
if obj._parent_name in obj.fields_get(cr, uid):
|
|
where.append((obj._parent_name,'=',object2 and object2.id or False))
|
|
|
|
resids = obj.search(cr,uid, where, context=ctx)
|
|
res = []
|
|
for bo in obj.browse(cr,uid,resids,context=ctx):
|
|
if not bo:
|
|
continue
|
|
name = getattr(bo,self.namefield)
|
|
if not name:
|
|
continue
|
|
# Yes! we can't do better but skip nameless records.
|
|
|
|
res.append(node_res_obj(name, self.dir_id, self, self.context, self.res_model, bo))
|
|
return res
|
|
|
|
def _get_ttag(self,cr):
|
|
return 'rdir-%d' % self.dir_id
|
|
|
|
class node_res_obj(node_class):
|
|
""" A special sibling to node_dir, which does only contain dynamically
|
|
created folders foreach resource in the foreign model.
|
|
All folders should be of type node_res_obj and merely behave like
|
|
node_dirs (with limited domain).
|
|
"""
|
|
our_type = 'collection'
|
|
def __init__(self, path, dir_id, parent, context, res_model, res_bo, res_id = None):
|
|
super(node_res_obj,self).__init__(path, parent,context)
|
|
assert parent
|
|
#todo: more info from dirr
|
|
self.dir_id = dir_id
|
|
self.mimetype = 'application/x-directory'
|
|
# 'httpd/unix-directory'
|
|
self.create_date = parent.create_date
|
|
# TODO: the write date should be MAX(file.write)..
|
|
self.write_date = parent.write_date
|
|
self.content_length = 0
|
|
self.res_model = res_model
|
|
self.domain = parent.domain
|
|
self.displayname = path
|
|
self.dctx_dict = parent.dctx_dict
|
|
if res_bo:
|
|
self.res_id = res_bo.id
|
|
dc2 = self.context.context
|
|
dc2.update(self.dctx)
|
|
dc2['res_model'] = res_model
|
|
dc2['res_id'] = res_bo.id
|
|
dc2['this'] = res_bo
|
|
for fld,expr in self.dctx_dict.items():
|
|
try:
|
|
self.dctx[fld] = safe_eval(expr,dc2)
|
|
except Exception,e:
|
|
print "Cannot eval %s for %s" % (expr, fld)
|
|
print e
|
|
pass
|
|
else:
|
|
self.res_id = res_id
|
|
|
|
def children(self,cr):
|
|
return self._child_get(cr) + self._file_get(cr)
|
|
|
|
def child(self,cr, name):
|
|
res = self._child_get(cr,name)
|
|
if res:
|
|
return res[0]
|
|
res = self._file_get(cr,name)
|
|
if res:
|
|
return res[0]
|
|
return None
|
|
|
|
def _file_get(self,cr, nodename=False):
|
|
res = []
|
|
cntobj = self.context._dirobj.pool.get('document.directory.content')
|
|
uid = self.context.uid
|
|
ctx = self.context.context.copy()
|
|
ctx.update(self.dctx)
|
|
where = [('directory_id','=',self.dir_id) ]
|
|
#if self.domain:
|
|
# where.extend(self.domain)
|
|
# print "res_obj file_get clause", where
|
|
ids = cntobj.search(cr,uid,where,context=ctx)
|
|
for content in cntobj.browse(cr,uid,ids,context=ctx):
|
|
res3 = cntobj._file_get(cr,self,nodename,content, context=ctx)
|
|
if res3:
|
|
res.extend(res3)
|
|
|
|
return res
|
|
|
|
def get_dav_props(self, cr):
|
|
res = {}
|
|
cntobj = self.context._dirobj.pool.get('document.directory.content')
|
|
uid = self.context.uid
|
|
ctx = self.context.context.copy()
|
|
ctx.update(self.dctx)
|
|
where = [('directory_id','=',self.dir_id) ]
|
|
ids = cntobj.search(cr,uid,where,context=ctx)
|
|
for content in cntobj.browse(cr,uid,ids,context=ctx):
|
|
if content.extension == '.ics': # FIXME: call the content class!
|
|
res['http://groupdav.org/'] = ('resourcetype',)
|
|
return res
|
|
|
|
def get_dav_eprop(self,cr,ns,prop):
|
|
if ns != 'http://groupdav.org/' or prop != 'resourcetype':
|
|
print "Who asked for %s:%s?" % (ns,prop)
|
|
return None
|
|
res = {}
|
|
cntobj = self.context._dirobj.pool.get('document.directory.content')
|
|
uid = self.context.uid
|
|
ctx = self.context.context.copy()
|
|
ctx.update(self.dctx)
|
|
where = [('directory_id','=',self.dir_id) ]
|
|
ids = cntobj.search(cr,uid,where,context=ctx)
|
|
for content in cntobj.browse(cr,uid,ids,context=ctx):
|
|
if content.extension == '.ics': # FIXME: call the content class!
|
|
return ('vevent-collection','http://groupdav.org/')
|
|
return None
|
|
|
|
def _child_get(self,cr,name = None):
|
|
dirobj = self.context._dirobj
|
|
uid = self.context.uid
|
|
ctx = self.context.context.copy()
|
|
ctx.update(self.dctx)
|
|
directory = dirobj.browse(cr, uid, self.dir_id)
|
|
obj = dirobj.pool.get(self.res_model)
|
|
where = []
|
|
res = []
|
|
if name:
|
|
where.append(('name','=',name))
|
|
|
|
# Directory Structure display in tree structure
|
|
if self.res_id and directory.ressource_tree:
|
|
where1 = []
|
|
if obj._parent_name in obj.fields_get(cr, uid):
|
|
where1 = where + [(obj._parent_name, '=', self.res_id)]
|
|
resids = obj.search(cr,uid, where1, context=ctx)
|
|
for bo in obj.browse(cr,uid,resids,context=ctx):
|
|
namefield = directory.resource_field or 'name'
|
|
if not bo:
|
|
continue
|
|
res_name = getattr(bo, namefield)
|
|
if not res_name:
|
|
continue
|
|
res.append(node_res_obj(res_name, self.dir_id, self, self.context, self.res_model, res_bo = bo))
|
|
|
|
|
|
where2 = where + [('parent_id','=',self.dir_id) ]
|
|
ids = dirobj.search(cr, uid, where2, context=ctx)
|
|
for dirr in dirobj.browse(cr, uid, ids, context=ctx):
|
|
if dirr.type == 'directory':
|
|
res.append(node_res_obj(dirr.name, dirr.id, self, self.context, self.res_model, res_bo = None, res_id = self.res_id))
|
|
elif dirr.type == 'ressource':
|
|
# child resources can be controlled by properly set dctx
|
|
res.append(node_res_dir(dirr.name,self,self.context, dirr, {'active_id': self.res_id}))
|
|
|
|
|
|
|
|
|
|
fil_obj = dirobj.pool.get('ir.attachment')
|
|
where3 = where2 + [('res_model', '=', self.res_model), ('res_id','=',self.res_id)]
|
|
# print "where clause for dir_obj", where2
|
|
ids = fil_obj.search(cr, uid, where3, context=ctx)
|
|
if ids:
|
|
for fil in fil_obj.browse(cr, uid, ids, context=ctx):
|
|
res.append(node_file(fil.name, self, self.context, fil))
|
|
|
|
|
|
# Get Child Ressource Directories
|
|
if directory.ressource_type_id and directory.ressource_type_id.id:
|
|
where4 = where + [('ressource_parent_type_id','=',directory.ressource_type_id.id)]
|
|
where5 = where4 + [('ressource_id','=',0)]
|
|
dirids = dirobj.search(cr,uid, where5)
|
|
where5 = where4 + [('ressource_id','=',self.res_id)]
|
|
dirids = dirids + dirobj.search(cr,uid, where5)
|
|
for dirr in dirobj.browse(cr, uid, dirids, context=ctx):
|
|
if dirr.type == 'directory' and not dirr.parent_id:
|
|
res.append(node_res_obj(dirr.name, dirr.id, self, self.context, self.res_model, res_bo = None, res_id = self.res_id))
|
|
if dirr.type == 'ressource':
|
|
res.append(node_res_dir(dirr.name, self, self.context, dirr, {'active_id': self.res_id}))
|
|
return res
|
|
|
|
def create_child(self,cr,path,data):
|
|
""" API function to create a child file object and node
|
|
Return the node_* created
|
|
"""
|
|
dirobj = self.context._dirobj
|
|
uid = self.context.uid
|
|
ctx = self.context.context.copy()
|
|
ctx.update(self.dctx)
|
|
fil_obj=dirobj.pool.get('ir.attachment')
|
|
val = {
|
|
'name': path,
|
|
'datas_fname': path,
|
|
'parent_id': self.dir_id,
|
|
'res_model': self.res_model,
|
|
'res_id': self.res_id,
|
|
# Datas are not set here
|
|
}
|
|
|
|
fil_id = fil_obj.create(cr,uid, val, context=ctx)
|
|
fil = fil_obj.browse(cr,uid,fil_id,context=ctx)
|
|
fnode = node_file(path,self,self.context,fil)
|
|
fnode.set_data(cr,data,fil)
|
|
return fnode
|
|
|
|
def _get_ttag(self,cr):
|
|
return 'rodir-%d-%d' % (self.dir_id,self.res_id)
|
|
|
|
class node_file(node_class):
|
|
our_type = 'file'
|
|
def __init__(self,path, parent, context, fil):
|
|
super(node_file,self).__init__(path, parent,context)
|
|
self.file_id = fil.id
|
|
#todo: more info from ir_attachment
|
|
if fil.file_type and '/' in fil.file_type:
|
|
self.mimetype = fil.file_type
|
|
self.create_date = fil.create_date
|
|
self.write_date = fil.write_date or fil.create_date
|
|
self.content_length = fil.file_size
|
|
self.displayname = fil.name
|
|
|
|
# This only propagates the problem to get_data. Better
|
|
# fix those files to point to the root dir.
|
|
if fil.parent_id:
|
|
self.storage_id = fil.parent_id.storage_id.id
|
|
else:
|
|
self.storage_id = None
|
|
|
|
|
|
def get_data(self, cr, fil_obj = None):
|
|
""" Retrieve the data for some file.
|
|
fil_obj may optionally be specified, and should be a browse object
|
|
for the file. This is useful when the caller has already initiated
|
|
the browse object. """
|
|
# this is where storage kicks in..
|
|
stor = self.storage_id
|
|
if not stor:
|
|
data_obj = self.context._dirobj.pool.get('ir.model.data')
|
|
data_id = data_obj._get_id(cr, self.context.uid, 'document', 'storage_db')
|
|
if data_id:
|
|
stor = data_obj.browse(cr, self.context.uid, data_id, context=self.context.context).res_id
|
|
assert stor
|
|
stobj = self.context._dirobj.pool.get('document.storage')
|
|
return stobj.get_data(cr,self.context.uid,stor, self,self.context.context, fil_obj)
|
|
|
|
def get_data_len(self, cr, fil_obj = None):
|
|
# TODO: verify with the storage object!
|
|
bin_size = self.context.context.get('bin_size', False)
|
|
if bin_size and not self.content_length:
|
|
self.content_length = fil_obj.db_datas
|
|
return self.content_length
|
|
|
|
def set_data(self, cr, data, fil_obj = None):
|
|
""" Store data at some file.
|
|
fil_obj may optionally be specified, and should be a browse object
|
|
for the file. This is useful when the caller has already initiated
|
|
the browse object. """
|
|
# this is where storage kicks in..
|
|
stor = self.storage_id
|
|
assert stor
|
|
stobj = self.context._dirobj.pool.get('document.storage')
|
|
return stobj.set_data(cr,self.context.uid,stor, self, data, self.context.context, fil_obj)
|
|
|
|
def _get_ttag(self,cr):
|
|
return 'file-%d' % self.file_id
|
|
|
|
class node_content(node_class):
|
|
our_type = 'content'
|
|
def __init__(self,path, parent, context, cnt, dctx = None, act_id=None):
|
|
super(node_content,self).__init__(path, parent,context)
|
|
self.cnt_id = cnt.id
|
|
self.create_date = False
|
|
self.write_date = False
|
|
self.content_length = False
|
|
self.extension = cnt.extension
|
|
self.report_id = cnt.report_id and cnt.report_id.id
|
|
#self.mimetype = cnt.extension.
|
|
self.displayname = path
|
|
if dctx:
|
|
self.dctx.update(dctx)
|
|
self.act_id = act_id
|
|
|
|
def fill_fields(self,cr,dctx = None):
|
|
""" Try to read the object and fill missing fields, like mimetype,
|
|
dates etc.
|
|
This function must be different from the constructor, because
|
|
it uses the db cursor.
|
|
"""
|
|
|
|
cr.execute('SELECT DISTINCT mimetype FROM document_directory_content_type WHERE active AND code = %s;',
|
|
(self.extension,))
|
|
res = cr.fetchall()
|
|
if res and res[0][0]:
|
|
self.mimetype = res[0][0]
|
|
|
|
|
|
def get_data(self, cr, fil_obj = None):
|
|
cntobj = self.context._dirobj.pool.get('document.directory.content')
|
|
ctx = self.context.context.copy()
|
|
ctx.update(self.dctx)
|
|
data = cntobj.process_read(cr,self.context.uid,self,ctx)
|
|
if data:
|
|
self.content_length = len(data)
|
|
return data
|
|
|
|
def get_data_len(self, cr, fil_obj = None):
|
|
if not self.content_length:
|
|
self.get_data(cr,fil_obj)
|
|
return self.content_length
|
|
|
|
def set_data(self, cr, data, fil_obj = None):
|
|
cntobj = self.context._dirobj.pool.get('document.directory.content')
|
|
ctx = self.context.context.copy()
|
|
ctx.update(self.dctx)
|
|
return cntobj.process_write(cr,self.context.uid,self, data,ctx)
|
|
|
|
def _get_ttag(self,cr):
|
|
return 'cnt-%d%s' % (self.cnt_id,(self.act_id and ('-' + str(self.act_id))) or '')
|
|
|
|
class old_class():
|
|
# the old code, remove..
|
|
def __init__(self, cr, uid, path, object, object2=False, context={}, content=False, type='collection', root=False):
|
|
self.cr = cr
|
|
def _file_get(self, nodename=False):
|
|
if not self.object:
|
|
return []
|
|
pool = pooler.get_pool(self.cr.dbname)
|
|
fobj = pool.get('ir.attachment')
|
|
res2 = []
|
|
where = []
|
|
if self.object2:
|
|
where.append( ('res_model','=',self.object2._name) )
|
|
where.append( ('res_id','=',self.object2.id) )
|
|
else:
|
|
where.append( ('parent_id','=',self.object.id) )
|
|
where.append( ('res_id','=',False) )
|
|
if nodename:
|
|
where.append( (fobj._rec_name,'=',nodename) )
|
|
for content in self.object.content_ids:
|
|
res3 = content._table._file_get(self,nodename,content)
|
|
if res3:
|
|
res2.extend(res3)
|
|
|
|
ids = fobj.search(self.cr, self.uid, where+[ ('parent_id','=',self.object and self.object.id or False) ])
|
|
if self.object and self.root and (self.object.type=='ressource'):
|
|
ids += fobj.search(self.cr, self.uid, where+[ ('parent_id','=',False) ])
|
|
res = fobj.browse(self.cr, self.uid, ids, context=self.context)
|
|
return map(lambda x: node_class(self.cr, self.uid, self.path+'/'+eval('x.'+fobj._rec_name), x, False, context=self.context, type='file', root=False), res) + res2
|
|
|
|
def get_translation(self,value,lang):
|
|
# Must go, it works on arbitrary models and could be ambiguous.
|
|
result = value
|
|
pool = pooler.get_pool(self.cr.dbname)
|
|
translation_ids = pool.get('ir.translation').search(self.cr, self.uid, [('value','=',value),('lang','=',lang),('type','=','model')])
|
|
if len(translation_ids):
|
|
tran_id = translation_ids[0]
|
|
translation = pool.get('ir.translation').read(self.cr, self.uid, tran_id, ['res_id','name'])
|
|
res_model,field_name = tuple(translation['name'].split(','))
|
|
res_id = translation['res_id']
|
|
res = pool.get(res_model).read(self.cr, self.uid, res_id, [field_name])
|
|
if res:
|
|
result = res[field_name]
|
|
return result
|
|
|
|
def directory_list_for_child(self,nodename,parent=False):
|
|
pool = pooler.get_pool(self.cr.dbname)
|
|
where = []
|
|
if nodename:
|
|
nodename = self.get_translation(nodename, self.context['lang'])
|
|
where.append(('name','=',nodename))
|
|
if (self.object and self.object.type=='directory') or not self.object2:
|
|
where.append(('parent_id','=',self.object and self.object.id or False))
|
|
else:
|
|
where.append(('parent_id','=',False))
|
|
if self.object:
|
|
where.append(('ressource_parent_type_id','=',self.object.ressource_type_id.id))
|
|
else:
|
|
where.append(('ressource_parent_type_id','=',False))
|
|
|
|
ids = pool.get('document.directory').search(self.cr, self.uid, where+[('ressource_id','=',0)])
|
|
if self.object2:
|
|
ids += pool.get('document.directory').search(self.cr, self.uid, where+[('ressource_id','=',self.object2.id)])
|
|
res = pool.get('document.directory').browse(self.cr, self.uid, ids, self.context)
|
|
return res
|
|
|
|
def _child_get(self, nodename=False):
|
|
if self.type not in ('collection','database'):
|
|
return []
|
|
res = self.directory_list_for_child(nodename)
|
|
result= map(lambda x: node_class(self.cr, self.uid, self.path+'/'+x.name, x, x.type=='directory' and self.object2 or False, context=self.context, root=self.root), res)
|
|
if self.type=='database':
|
|
pool = pooler.get_pool(self.cr.dbname)
|
|
fobj = pool.get('ir.attachment')
|
|
vargs = [('parent_id','=',False),('res_id','=',False)]
|
|
if nodename:
|
|
vargs.append((fobj._rec_name,'=',nodename))
|
|
file_ids=fobj.search(self.cr,self.uid,vargs)
|
|
|
|
res = fobj.browse(self.cr, self.uid, file_ids, context=self.context)
|
|
result +=map(lambda x: node_class(self.cr, self.uid, self.path+'/'+eval('x.'+fobj._rec_name), x, False, context=self.context, type='file', root=self.root), res)
|
|
if self.type=='collection' and self.object.type=="ressource":
|
|
where = self.object.domain and eval(self.object.domain, {'active_id':self.root, 'uid':self.uid}) or []
|
|
pool = pooler.get_pool(self.cr.dbname)
|
|
obj = pool.get(self.object.ressource_type_id.model)
|
|
_dirname_field = obj._rec_name
|
|
if len(obj.fields_get(self.cr, self.uid, ['dirname'])):
|
|
_dirname_field = 'dirname'
|
|
|
|
name_for = obj._name.split('.')[-1]
|
|
if nodename and nodename.find(name_for) == 0 :
|
|
id = int(nodename.replace(name_for,''))
|
|
where.append(('id','=',id))
|
|
elif nodename:
|
|
if nodename.find('__') :
|
|
nodename=nodename.replace('__','/')
|
|
for invalid in INVALID_CHARS:
|
|
if nodename.find(INVALID_CHARS[invalid]) :
|
|
nodename=nodename.replace(INVALID_CHARS[invalid],invalid)
|
|
nodename = self.get_translation(nodename, self.context['lang'])
|
|
where.append((_dirname_field,'=',nodename))
|
|
|
|
if self.object.ressource_tree:
|
|
if obj._parent_name in obj.fields_get(self.cr,self.uid):
|
|
where.append((obj._parent_name,'=',self.object2 and self.object2.id or False))
|
|
ids = obj.search(self.cr, self.uid, where)
|
|
res = obj.browse(self.cr, self.uid, ids,self.context)
|
|
result+= map(lambda x: node_class(self.cr, self.uid, self.path+'/'+x.name.replace('/','__'), self.object, x, context=self.context, root=x.id), res)
|
|
return result
|
|
else :
|
|
if self.object2:
|
|
return result
|
|
else:
|
|
if self.object2:
|
|
return result
|
|
|
|
|
|
ids = obj.search(self.cr, self.uid, where)
|
|
res = obj.browse(self.cr, self.uid, ids,self.context)
|
|
for r in res:
|
|
if len(obj.fields_get(self.cr, self.uid, [_dirname_field])):
|
|
r.name = eval('r.'+_dirname_field)
|
|
else:
|
|
r.name = False
|
|
if not r.name:
|
|
r.name = name_for + '%d'%r.id
|
|
for invalid in INVALID_CHARS:
|
|
if r.name.find(invalid) :
|
|
r.name = r.name.replace(invalid,INVALID_CHARS[invalid])
|
|
result2 = map(lambda x: node_class(self.cr, self.uid, self.path+'/'+x.name.replace('/','__'), self.object, x, context=self.context, root=x.id), res)
|
|
if result2:
|
|
if self.object.ressource_tree:
|
|
result += result2
|
|
else:
|
|
result = result2
|
|
return result
|
|
|
|
|
|
def path_get(self):
|
|
path = self.path
|
|
if self.path[0]=='/':
|
|
path = self.path[1:]
|
|
return path
|