add DocumentsFolder listing documents from Tabellio
Creating dynamic DmsFile as objects for the moment.
This commit is contained in:
parent
0dc5fe57ed
commit
04506ca850
1
setup.py
1
setup.py
|
@ -45,6 +45,7 @@ setup(
|
|||
'setuptools',
|
||||
'five.grok',
|
||||
'plone.app.contenttypes',
|
||||
'Products.SQLAlchemyDA',
|
||||
],
|
||||
entry_points="""
|
||||
[z3c.autoinclude.plugin]
|
||||
|
|
|
@ -11,4 +11,12 @@
|
|||
<include package="five.grok" />
|
||||
<grok:grok package="." />
|
||||
|
||||
<genericsetup:registerProfile
|
||||
name="default"
|
||||
title="pfwbged.tabellio"
|
||||
directory="profiles/default"
|
||||
provides="Products.GenericSetup.interfaces.EXTENSION"
|
||||
/>
|
||||
|
||||
|
||||
</configure>
|
||||
|
|
|
@ -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)
|
|
@ -0,0 +1,6 @@
|
|||
<metadata>
|
||||
<version>0.1</version>
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
</metadata>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<object name="portal_types" meta_type="Plone Types Tool">
|
||||
<property name="title">Controls the available content types in your portal</property>
|
||||
<object name="pfwbged.tabellio.documentsfolder" meta_type="Dexterity FTI"/>
|
||||
</object>
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0"?>
|
||||
<object name="pfwbged.tabellio.documentsfolder" meta_type="Dexterity FTI" i18n:domain="plone"
|
||||
xmlns:i18n="http://xml.zope.org/namespaces/i18n">
|
||||
<property name="title" i18n:translate="">Documents from Tabellio</property>
|
||||
<property name="icon_expr">string:${portal_url}/++resource++pfwbged.tabellio.documentsfolder_icon.png</property>
|
||||
<!--<property name="factory">pfwbged.tabellio.documentsfolder</property>-->
|
||||
<property name="add_view_expr">string:${folder_url}/++add++pfwbged.tabellio.documentsfolder</property>
|
||||
<property name="link_target"></property>
|
||||
<property name="immediate_view">view</property>
|
||||
<property name="global_allow">True</property>
|
||||
<property name="filter_content_types">True</property>
|
||||
<property name="allow_discussion">False</property>
|
||||
<property name="default_view">view</property>
|
||||
<property name="view_methods">
|
||||
<element value="view"/>
|
||||
</property>
|
||||
<property name="default_view_fallback">False</property>
|
||||
<property name="add_permission">cmf.AddPortalContent</property>
|
||||
<property name="klass">pfwbged.tabellio.documents.DocumentsFolder</property>
|
||||
<property name="behaviors">
|
||||
<element value="plone.app.content.interfaces.INameFromTitle"/>
|
||||
<element value="plone.app.dexterity.behaviors.metadata.IBasic"/>
|
||||
</property>
|
||||
|
||||
<!-- Contained Types -->
|
||||
<property name="filter_content_types">True</property>
|
||||
<property name="allowed_content_types" purge="False">
|
||||
</property>
|
||||
|
||||
<!-- DO NOT use a model_source or it removes manually added fields while reapplying the profile -->
|
||||
<!--property name="model_source" /-->
|
||||
<property name="schema">pfwbged.tabellio.documents.IDocumentsFolder</property>
|
||||
<alias from="(Default)" to="(dynamic view)"/>
|
||||
<alias from="edit" to="@@edit"/>
|
||||
<alias from="sharing" to="@@sharing"/>
|
||||
<alias from="view" to="(selected layout)"/>
|
||||
<action title="View" action_id="view" category="object" condition_expr=""
|
||||
description="" icon_expr="" link_target="" url_expr="string:${object_url}"
|
||||
visible="True">
|
||||
<permission value="View"/>
|
||||
</action>
|
||||
<action title="Edit" action_id="edit" category="object" condition_expr=""
|
||||
description="" icon_expr="" link_target=""
|
||||
url_expr="string:${object_url}/edit" visible="True">
|
||||
<permission value="Modify portal content"/>
|
||||
</action>
|
||||
</object>
|
Reference in New Issue