From 04506ca8502230342821463368dab715947e9730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Tue, 18 Nov 2014 14:11:32 +0100 Subject: [PATCH] add DocumentsFolder listing documents from Tabellio Creating dynamic DmsFile as objects for the moment. --- setup.py | 1 + src/pfwbged/tabellio/configure.zcml | 8 + src/pfwbged/tabellio/documents.py | 175 ++++++++++++++++++ .../tabellio/profiles/default/metadata.xml | 6 + .../tabellio/profiles/default/types.xml | 5 + .../pfwbged.tabellio.documentsfolder.xml | 47 +++++ 6 files changed, 242 insertions(+) create mode 100644 src/pfwbged/tabellio/documents.py create mode 100644 src/pfwbged/tabellio/profiles/default/metadata.xml create mode 100644 src/pfwbged/tabellio/profiles/default/types.xml create mode 100644 src/pfwbged/tabellio/profiles/default/types/pfwbged.tabellio.documentsfolder.xml diff --git a/setup.py b/setup.py index 3eb6be9..5e4edd9 100644 --- a/setup.py +++ b/setup.py @@ -45,6 +45,7 @@ setup( 'setuptools', 'five.grok', 'plone.app.contenttypes', + 'Products.SQLAlchemyDA', ], entry_points=""" [z3c.autoinclude.plugin] diff --git a/src/pfwbged/tabellio/configure.zcml b/src/pfwbged/tabellio/configure.zcml index 64ab71a..15d1239 100644 --- a/src/pfwbged/tabellio/configure.zcml +++ b/src/pfwbged/tabellio/configure.zcml @@ -11,4 +11,12 @@ + + + diff --git a/src/pfwbged/tabellio/documents.py b/src/pfwbged/tabellio/documents.py new file mode 100644 index 0000000..336d303 --- /dev/null +++ b/src/pfwbged/tabellio/documents.py @@ -0,0 +1,175 @@ +import datetime + +from plone import api +from five import grok +from zope.interface import implements +from AccessControl import ClassSecurityInfo, getSecurityManager +from AccessControl.Permissions import access_contents_information + +from plone.dexterity.content import Container +from plone.supermodel import model + +class IDocumentsFolder(model.Schema): + pass + + +class DocumentsFolder(Container): + implements(IDocumentsFolder) + security = ClassSecurityInfo() + + _v_dbcache = None # volatile attribute + + @property + def db_connection(self): + return api.portal.get().db._wrapper.connection + + def __iter__(self): + if not self._v_dbcache: + self._v_dbcache = {} + + cursor = self.db_connection.cursor() + cursor.execute('''SELECT id, ts, intit, textdefts + FROM t_document''') + while True: + row = cursor.fetchone() + if row is None: + break + rowid, ts, intit, textdfts = row + self._v_dbcache[rowid] = {'ts': ts, 'intit': intit, 'textdfts': textdfts} + yield rowid + + cursor.close() + + def __getitem__(self, id): + try: + int(id) + except ValueError: + pass + else: + cursor = self.db_connection.cursor() + cursor.execute('''SELECT id, intit, sess + FROM t_document + WHERE id = %(id)s''', {'id': id}) + row = cursor.fetchone() + if row is None: + return super(DocumentsFolder, self).__getitem__(id) + cursor.close() + + row_id, intit, sess = row + from collective.dms.basecontent.dmsfile import DmsFile + t = DmsFile(id=row_id, title=intit, label=sess) + t.portal_type = 'dmsmainfile' + from Acquisition import aq_chain + return aq_chain(t.__of__(self))[0] + return super(DocumentsFolder, self).__getitem__(id) + + def keys(self): + return list(self.__iter__()) + + def getFolderContents(self, *args, **kwargs): + folder = self + parent_path = '/'.join(folder.getPhysicalPath()) + '/' + parent_url = folder.absolute_url() + '/' + + class FakeBrain(object): + def __init__(self, object_id): + self.id = object_id + self._object = None + self.getId = object_id + self.getObjSize = 0 + self.is_folderish = True + self.portal_type = 'dmsmainfile' + self.Creator = 'Tabellio' + + def Type(self): + return self.portal_type + + def get_object_attibute(self, attribute): + if not self._object: + self._object = folder[self.id] + return getattr(self._object, attribute) + + @property + def modified(self): + if folder._v_dbcache and self.id in folder._v_dbcache: + return folder._v_dbcache[self.id]['ts'] + return datetime.datetime.now() + + def ModificationDate(self): + return self.modified + + @property + def CreationDate(self): + if folder._v_dbcache and self.id in folder._v_dbcache: + t = folder._v_dbcache[self.id]['textdfts'] + if t: + return t + return datetime.datetime.now() + + @property + def title(self): + if folder._v_dbcache and self.id in folder._v_dbcache: + return folder._v_dbcache[self.id]['intit'] + return self.get_object_attibute('title') + + def pretty_title_or_id(self): + if self.title: + return self.title + return self.id + + def Title(self): + return self.title + + review_state = None + Description = None + + def getPath(self): + return parent_path + self.id + + def getURL(self, relative=True): + if relative: + return self.id + return parent_url + self.id + + # plone.batching.batch doesn't support generators + t = [] + for k in self.__iter__(): + t.append(FakeBrain(k)) + return t + + # Acquisition wrappers don't support the __iter__ slot, so re-implement + # iteritems to call __iter__ directly. + def iteritems(self): + for k in self.__iter__(): + yield (k, self[k]) + + security.declareProtected(access_contents_information, + 'objectIds') + def objectIds(self, spec=None): + # Returns a list of subobject ids of the current object. + # If 'spec' is specified, returns objects whose meta_type + # matches 'spec'. + assert spec is None, 'spec argument unsupported' + return self.__iter__() + + + security.declareProtected(access_contents_information, + 'objectValues') + def objectValues(self, spec=None): + # Returns a list of actual subobjects of the current object. + # If 'spec' is specified, returns only objects whose meta_type + # match 'spec'. + assert spec is None, 'spec argument unsupported' + for k in self.__iter__(): + yield self[k] + + security.declareProtected(access_contents_information, + 'objectItems') + def objectItems(self, spec=None): + # Returns a list of (id, subobject) tuples of the current object. + # If 'spec' is specified, returns only objects whose meta_type match + # 'spec' + assert spec is None, 'spec argument unsupported' + return self.iteritems() + +grok.context(DocumentsFolder) diff --git a/src/pfwbged/tabellio/profiles/default/metadata.xml b/src/pfwbged/tabellio/profiles/default/metadata.xml new file mode 100644 index 0000000..58812bd --- /dev/null +++ b/src/pfwbged/tabellio/profiles/default/metadata.xml @@ -0,0 +1,6 @@ + + 0.1 + + + + diff --git a/src/pfwbged/tabellio/profiles/default/types.xml b/src/pfwbged/tabellio/profiles/default/types.xml new file mode 100644 index 0000000..13c4681 --- /dev/null +++ b/src/pfwbged/tabellio/profiles/default/types.xml @@ -0,0 +1,5 @@ + + + Controls the available content types in your portal + + diff --git a/src/pfwbged/tabellio/profiles/default/types/pfwbged.tabellio.documentsfolder.xml b/src/pfwbged/tabellio/profiles/default/types/pfwbged.tabellio.documentsfolder.xml new file mode 100644 index 0000000..7a58827 --- /dev/null +++ b/src/pfwbged/tabellio/profiles/default/types/pfwbged.tabellio.documentsfolder.xml @@ -0,0 +1,47 @@ + + + Documents from Tabellio + string:${portal_url}/++resource++pfwbged.tabellio.documentsfolder_icon.png + + string:${folder_url}/++add++pfwbged.tabellio.documentsfolder + + view + True + True + False + view + + + + False + cmf.AddPortalContent + pfwbged.tabellio.documents.DocumentsFolder + + + + + + + True + + + + + + pfwbged.tabellio.documents.IDocumentsFolder + + + + + + + + + + +