""" Baseclass for representation-independent content. """ from Globals import InitializeClass from AccessControl import ClassSecurityInfo from Products.Archetypes.public import * from Products.Archetypes.debug import log from Products.CMFCore.utils import getToolByName from Products.CMFCore.CMFCorePermissions import ModifyPortalContent, AddPortalContent, View from Acquisition import Implicit from Acquisition import aq_base, aq_inner, aq_parent from OFS.ObjectManager import BeforeDeleteException from Products.ATRepresentations.interfaces import IRepresentable from Products.ATRepresentations.config import * try: True except NameError: True=1 False=0 class ATRepsBaseObject(Implicit): """ Base class for representable objects """ __implements__ = (IRepresentable,) security = ClassSecurityInfo() security.declareProtected(View, 'isRepresentable') def isRepresentable(self): """Tells that this object is used in a representation context""" return True security.declareProtected(View, 'isRepresentation') def isRepresentation(self): """Tells whether this object is used in a representation context""" return self.getReferenceImpl(RELATIONSHIP) or self.getBackReferenceImpl(RELATIONSHIP) or False security.declareProtected(View, 'representationsCount') def representationsCount(self): """Get count of linked representations""" return len(self.getRepresentations()) security.declareProtected(AddPortalContent, 'addRepresentation') def addRepresentation(self, *args, **kwargs): """Add a representation""" parent = aq_parent(aq_inner(self)) canonicalRepresentation = self.getCanonicalRepresentation() id = '%s-rep%s'%(canonicalRepresentation.getId(), self.representationsCount()) parent.checkIdAvailable(id) parent.invokeFactory(self.portal_type, id, *args, **kwargs) o = getattr(parent, id) o.initializeRepresentation() o.addReference(canonicalRepresentation, RELATIONSHIP) self.invalidateRepresentationCache() o.reindexObject() return o security.declareProtected(ModifyPortalContent, 'removeRepresentation') def removeRepresentation(self, object_id): """Remove a representation, pass on to layer""" object = self.getRepresentation(object_id) if object.isCanonicalRepresentation(): # Update representations to point to this one self.setCanonicalRepresentation() representationParent = aq_parent(aq_inner(object)) representationParent.manage_delObjects([object.getId(),]) self.invalidateRepresentationCache() security.declareProtected(View, 'getRepresentations') def getRepresentations(self): """Return a list (object, wf_state), pass on to layer""" if self.isCanonicalRepresentation(): if CACHE_REPRESENTATIONS and getattr(self, '_v_representations', None): return self._v_representations result = [] wftool = getToolByName(self, 'portal_workflow') result.append((self, wftool.getInfoFor(self, 'review_state'))) for obj in self.getBRefs(RELATIONSHIP): result.append((obj, wftool.getInfoFor(obj, 'review_state'))) if CACHE_REPRESENTATIONS: self._v_representations = result return result else: return self.getCanonicalRepresentation().getRepresentations() security.declareProtected(View, 'getRepresentation') def getRepresentation(self, id): """Return the object with id among representations""" representations = self.getCanonicalRepresentation().getRepresentations() for repr, wf_state in representations: if repr.getId() == id: return repr raise AttributeError, 'Representation %s not found' % id security.declareProtected(View, 'getNonCanonicalRepresentations') def getNonCanonicalRepresentations(self): """Return a list of (object, wf_state)""" representations = self.getRepresentations() non_main = [] for repr, wf_state in representations: if not repr.isCanonicalRepresentation(): non_main.append((repr, wf_state)) return non_main security.declareProtected(View, 'isCanonicalRepresentation') def isCanonicalRepresentation(self): """Tells whether this is the canonical representation""" # This is canonical there are no representationOf references return not self.getReferenceImpl(RELATIONSHIP) and True or False security.declareProtected(ModifyPortalContent, 'setCanonicalRepresentation') def setCanonicalRepresentation(self): """Sets the canonical representation """ # This requires changing references if not self.isCanonicalRepresentation(): representations = self.getRepresentations() #import pdb; pdb.set_trace() for obj, wfstate in representations: obj.deleteReferences(RELATIONSHIP) for obj, wfstate in representations: if obj != self: obj.addReference(self, RELATIONSHIP) self.invalidateRepresentationCache() security.declareProtected(View, 'getCanonicalRepresentation') def getCanonicalRepresentation(self): """Returns the canonical representation""" if CACHE_REPRESENTATIONS and getattr(self, '_v_main_representation', None): return self._v_main_representation ret = None if self.isCanonicalRepresentation(): ret = self else: refs = self.getRefs(RELATIONSHIP) ret = refs and refs[0] or None if CACHE_REPRESENTATIONS: self._v_main_representation = ret return ret security.declareProtected(ModifyPortalContent, 'initializeRepresentation') def initializeRepresentation(self): """Initializes the representation object""" pass security.declarePrivate('invalidateRepresentationCache') def invalidateRepresentationCache(self): if CACHE_REPRESENTATIONS: if hasattr(self, '_v_main_representation'): delattr(self, '_v_main_representation') if self.isCanonicalRepresentation(): if hasattr(self, '_v_representations'): delattr(self, '_v_representations') else: self.getCanonicalRepresentation().invalidateRepresentationCache() security.declarePrivate('manage_beforeDelete') def manage_beforeDelete(self, item, container): # Called from manage_beforeDelete() of subclasses to # veto deletion of the canonical representation object. # # If the _v_cp_refs still is True *while* deleting, # it is not actually a delete but a move! # There's no need to protect that case. moving = getattr(self, '_v_cp_refs', False) if moving: return if CANONICAL_DELETE_PROTECTION: if self.isCanonicalRepresentation() and self.getNonCanonicalRepresentations(): raise BeforeDeleteException, 'Please delete representations first.' InitializeClass(ATRepsBaseObject)