[Erp5-report] r13731 - /erp5/trunk/products/ERP5/Document/Document.py
nobody at svn.erp5.org
nobody at svn.erp5.org
Tue Mar 27 23:18:17 CEST 2007
Author: jp
Date: Tue Mar 27 23:18:16 2007
New Revision: 13731
URL: http://svn.erp5.org?rev=13731&view=rev
Log:
Finalised and simplified the revision system spec.
Modified:
erp5/trunk/products/ERP5/Document/Document.py
Modified: erp5/trunk/products/ERP5/Document/Document.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/Document.py?rev=13731&r1=13730&r2=13731&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/Document.py (original)
+++ erp5/trunk/products/ERP5/Document/Document.py Tue Mar 27 23:18:16 2007
@@ -366,6 +366,19 @@
Default implementation uses DocumentReferenceConstraint to check if the
reference/language/version triplet is unique. Additional constraints
can be added if necessary.
+
+ NOTE: Document.py supports a notion of revision which is very specific.
+ The underlying concept is that, as soon as a document has a reference,
+ the association of (reference, version, language) must be unique
+ accross the whole system. This means that a given document in a given
+ version in a given language is unique. The underlying idea is similar
+ to the one in a Wiki system in which each page is unique and acts
+ the the atom of collaboration. In the case of ERP5, if a team collaborates
+ on a Text document written with an offline word processor, all
+ updates should be placed inside the same object. A Contribution
+ will thus modify an existing document, if allowed from security
+ point of view, and increase the revision number. Same goes for
+ properties (title). Each change generates a new revision.
"""
meta_type = 'ERP5 Document'
@@ -489,7 +502,7 @@
return bool(self.getUrlString())
### Relation getters
- security.declareProtected(Permissions.View, 'getSearchableReferenceList')
+ security.declareProtected(Permissions.AccessContentsInformation, 'getSearchableReferenceList')
def getSearchableReferenceList(self):
"""
This method returns a list of dictionaries which can
@@ -509,7 +522,7 @@
res = [(r.group(), r.groupdict()) for r in res]
return res
- security.declareProtected(Permissions.View, 'getImplicitSuccessorValueList')
+ security.declareProtected(Permissions.AccessContentsInformation, 'getImplicitSuccessorValueList')
def getImplicitSuccessorValueList(self):
"""
Find objects which we are referencing (if our text_content contains
@@ -543,7 +556,7 @@
res_dict = dict.fromkeys(res)
return res_dict.keys()
- security.declareProtected(Permissions.View, 'getImplicitPredecessorValueList')
+ security.declareProtected(Permissions.AccessContentsInformation, 'getImplicitPredecessorValueList')
def getImplicitPredecessorValueList(self):
"""
This function tries to find document which are referencing us - by reference only, or
@@ -574,7 +587,7 @@
ref = self.getReference()
return [o for o in di.keys() if o.getReference() != ref] # every object has its own reference in SearchableText
- security.declareProtected(Permissions.View, 'getImplicitSimilarValueList')
+ security.declareProtected(Permissions.AccessContentsInformation, 'getImplicitSimilarValueList')
def getImplicitSimilarValueList(self):
"""
Analyses content of documents to find out by the content which documents
@@ -584,7 +597,7 @@
"""
return []
- security.declareProtected(Permissions.View, 'getSimilarCloudValueList')
+ security.declareProtected(Permissions.AccessContentsInformation, 'getSimilarCloudValueList')
def getSimilarCloudValueList(self, depth=0):
"""
Returns all documents which are similar to us, directly or indirectly, and
@@ -619,17 +632,6 @@
lista_latest.pop(self()) # remove this document
return lista_latest.keys()
-
- security.declareProtected(Permissions.View, 'hasFile')
- def hasFile(self):
- """
- Checks whether we have an initial file
- """
- _marker = []
- if getattr(self,'data', _marker) is not _marker: # XXX-JPS - use propertysheet accessors
- d = getattr(self, 'data')
- return d is not None and d != ''
- return False
### Version and language getters - might be moved one day to a mixin class in base
security.declareProtected(Permissions.View, 'getLatestVersionValue')
@@ -693,101 +695,58 @@
if language: kw['language'] = language
return catalog(**kw)
- security.declareProtected(Permissions.View, 'isVersionUnique')
+ security.declareProtected(Permissions.AccessContentsInformation, 'isVersionUnique')
def isVersionUnique(self):
"""
- Returns true if no other document of the same
- portal_type and reference has the same version and language
-
- XXX should delegate to script with proxy roles
- XXX-JPS revision ?
- """
+ Returns true if no other document exists with the same
+ reference, version and language, or if the current
+ document has no reference.
+ """
+ if not self.getReference():
+ return 1
catalog = getToolByName(self, 'portal_catalog', None)
- # XXX why this does not work???
- #return catalog.countResults(portal_type=self.getPortalType(),
- #reference=self.getReference(),
- #version=self.getVersion(),
- #language=self.getLanguage(),
- #) <= 1
- return len(catalog(portal_type=self.getPortalType(),
- reference=self.getReference(),
- version=self.getVersion(),
- language=self.getLanguage(),
- )) <= 1
-
- security.declareProtected(Permissions.View, 'getLatestRevisionValue')
- def getLatestRevisionValue(self):
- """
- Returns the latest revision of ourselves
- """
- if not self._checkCompleteCoordinates():
- return None
- catalog = getToolByName(self, 'portal_catalog', None)
- res = catalog(
- reference=self.getReference(),
- language=self.getLanguage(),
- version=self.getVersion(),
- sort_on=(('revision','descending'),)
- )
- if len(res) == 0:
- return None
- return res[0].getObject()
-
- security.declareProtected(Permissions.View, 'getRevisionValueList')
- def getRevisionValueList(self):
- """
- Returns a list revision strings for a given reference, version, language
- XXX should it return revision strings, or docs (as the func name would suggest)?
-
- XXX-JPS return values - getRevisionList returns revisions
- """
- # Use portal_catalog
- if not self._checkCompleteCoordinates():
- return []
- res = self.portal_catalog(reference=self.getReference(),
- language=self.getLanguage(),
- version=self.getVersion()
- )
- d = {}
- for r in res:
- d[r.getRevision()] = True
- revs = d.keys()
- revs.sort(reverse=True)
- return revs
-
- security.declarePrivate('_checkCompleteCoordinates')
- def _checkCompleteCoordinates(self):
- """
- test if the doc has all coordinates
-
- XXX-JPS - revision ?
- """
- reference = self.getReference()
- version = self.getVersion()
- language = self.getLanguage()
- return (reference and version and language)
-
- security.declareProtected(Permissions.ModifyPortalContent, 'setNewRevision')
- def setNewRevision(self, immediate_reindex=False):
- """
- Set a new revision number automatically
- Delegates to ZMI script because revision numbering policies can be different.
- Should be called by interaction workflow upon appropriate action.
-
- Sometimes we should reindex immediately, to avoid other doc setting
- the same revision (if revisions are global and there is heavy traffic)
- """
- # Use portal_catalog without security (proxy roles on scripts)
- method = self._getTypeBasedMethod('getNewRevision',
- fallback_script_id = 'Document_getNewRevision')
- new_rev = method()
- self.setRevision(new_rev)
- if immediate_reindex:
- self.immediateReindexObject()
- else:
- self.reindexObject()
-
- security.declareProtected(Permissions.View, 'getLanguageList')
+ # This method has been reported not to work. Extra test needed.
+ return catalog.unrestrictedCountResults(portal_type=self.getPortalDocumentTypeList(),
+ reference=self.getReference(),
+ version=self.getVersion(),
+ language=self.getLanguage(),
+ ) <= 1
+
+ security.declareProtected(Permissions.AccessContentsInformation, 'getRevision')
+ def getRevision(self):
+ """
+ Returns the current revision by analysing the change log
+ of the current object.
+
+ NOTE: for now, workflow choice is hardcoded. This is
+ an optimisation hack. If a document does neither use
+ edit_workflow or processing_status_workflow, the
+ first workflow in the chain has prioriot. Better
+ implementation would require to be able to define
+ which workflow in a chain is the default one for
+ revision tracking (and for modification date).
+ """
+ portal_workflow = getToolByName(self, 'portal_workflow')
+ wf_list = list(portal_workflow.getWorkflowsFor(self))
+ wf = portal_workflow.getWorkflowById('edit_workflow')
+ if wf is not None: wf_list = [wf] + wf_list
+ wf = portal_workflow.getWorkflowById('processing_status_workflow')
+ if wf is not None: wf_list = [wf] + wf_list
+ for wf in wf_list:
+ history = wf.getInfoFor(self, 'history', None)
+ if history:
+ return len(filter(lambda x:x.get('action', None) in ('edit', 'upload'), history))
+ return None
+
+ security.declareProtected(Permissions.AccessContentsInformation, 'getRevisionList')
+ def getRevisionList(self):
+ """
+ Returns the list of revision numbers of the current document
+ by by analysing the change log of the current object.
+ """
+ return range(0, self.getRevision())
+
+ security.declareProtected(Permissions.AccessContentsInformation, 'getLanguageList')
def getLanguageList(self, version=None):
"""
Returns a list of languages which this document is available in
@@ -802,7 +761,7 @@
kw['version'] = version
return map(lambda o:o.getLanguage(), catalog(**kw))
- security.declareProtected(Permissions.View, 'getOriginalLanguage')
+ security.declareProtected(Permissions.AccessContentsInformation, 'getOriginalLanguage')
def getOriginalLanguage(self):
"""
Returns the original language of this document.
@@ -877,6 +836,23 @@
# disappear within a given transaction
return kw
+ security.declareProtected(Permissions.AccessContentsInformation, 'getStandardFileName')
+ def getStandardFileName(self):
+ """
+ Returns the document coordinates as a standard file name. This
+ method is the reverse of getPropertyDictFromFileName.
+
+ NOTE: this method must be overloadable by types base method with fallback
+ """
+ if self.getReference():
+ file_name = self.getReference()
+ else:
+ file_name = self.getTitleOrId()
+ if self.getVersion():
+ file_name = file_name + '-%s' % self.getVersion()
+ if self.getLanguage():
+ file_name = file_name + '-%s' % self.getLanguage()
+ return file_name
### Metadata disovery and ingestion methods
security.declareProtected(Permissions.ModifyPortalContent, 'discoverMetadata')
@@ -1151,7 +1127,7 @@
base_url = '/'.join(base_url_list[:-1])
return base_url
- # Alarm date calculation
+ # Alarm date calculation - this method should be moved out ASAP
security.declareProtected(Permissions.AccessContentsInformation, 'getNextAlarmDate')
def getNextAlarmDate(self):
"""
@@ -1160,22 +1136,3 @@
classes is needed.
"""
return DateTime() + 10
-
- # Standard File Naming
- security.declareProtected(Permissions.AccessContentsInformation, 'getStandardFileName')
- def getStandardFileName(self):
- """
- Returns the document coordinates as a standard file name.
-
- NOTE: this method must be overloadable by types base method with fallback
- """
- if self.getReference():
- file_name = self.getReference()
- else:
- file_name = self.getTitleOrId()
- if self.getVersion():
- file_name = file_name + '-%s' % self.getVersion()
- if self.getLanguage():
- file_name = file_name + '-%s' % self.getLanguage()
- return file_name
-
More information about the Erp5-report
mailing list