diff --git a/concept.py b/concept.py index 5970dd9..e4f5817 100644 --- a/concept.py +++ b/concept.py @@ -230,8 +230,8 @@ class Concept(Contained, Persistent): registry = component.getUtility(IRelationRegistry) for rel in self.getChildRelations(predicates, child): if order is None or rel.order == order: - notify(DeassignmentEvent(self, rel)) registry.unregister(rel) + notify(DeassignmentEvent(self, rel)) def deassignParent(self, parent, predicates=None): parent.deassignChild(self, predicates) @@ -269,8 +269,8 @@ class Concept(Contained, Persistent): registry = component.getUtility(IRelationRegistry) for rel in self.getResourceRelations(predicates, resource): if order is None or rel.order == order: - notify(DeassignmentEvent(self, rel)) registry.unregister(rel) + notify(DeassignmentEvent(self, rel)) # combined children+resources query diff --git a/organize/stateful/base.py b/organize/stateful/base.py index a81284c..102d8e8 100644 --- a/organize/stateful/base.py +++ b/organize/stateful/base.py @@ -22,13 +22,16 @@ Basic implementations for stateful objects and adapters. $Id$ """ +from zope.app.catalog.interfaces import ICatalog from zope import component -from zope.component import adapts +from zope.component import adapts, adapter +from cybertools.meta.interfaces import IOptions from cybertools.stateful.base import Stateful as BaseStateful -from cybertools.stateful.base import StatefulAdapter -from cybertools.stateful.interfaces import IStatesDefinition -from loops.interfaces import ILoopsObject +from cybertools.stateful.base import StatefulAdapter, IndexInfo +from cybertools.stateful.interfaces import IStatesDefinition, ITransitionEvent +from loops.interfaces import ILoopsObject, IResource +from loops import util class Stateful(BaseStateful): @@ -46,3 +49,21 @@ class SimplePublishable(StatefulLoopsObject): statesDefinition = 'loops.simple_publishing' + +class StatefulResourceIndexInfo(IndexInfo): + + adapts(IResource) + + @property + def availableStatesDefinitions(self): + options = IOptions(self.context.getLoopsRoot()) + return options('organize.stateful.resource', ()) + + +@adapter(IResource, ITransitionEvent) +def handleTransition(self, obj, event): + previous = event.previousState + next = event.transition.targetState + if next != previous: + cat = getUtility(ICatalog) + cat.index_doc(int(util.getUidForObject(obj)), obj) diff --git a/organize/stateful/configure.zcml b/organize/stateful/configure.zcml index 64cf820..d207f81 100644 --- a/organize/stateful/configure.zcml +++ b/organize/stateful/configure.zcml @@ -5,6 +5,13 @@ xmlns:browser="http://namespaces.zope.org/browser" i18n_domain="loops"> + + + + + + diff --git a/organize/stateful/quality.py b/organize/stateful/quality.py index f2c3dc8..d50fa76 100644 --- a/organize/stateful/quality.py +++ b/organize/stateful/quality.py @@ -34,6 +34,7 @@ from cybertools.stateful.interfaces import IStatesDefinition, IStateful from loops.interfaces import IAssignmentEvent, IDeassignmentEvent from loops.interfaces import ILoopsObject, IResource from loops.organize.stateful.base import StatefulLoopsObject +from loops.versioning.interfaces import IVersionable @implementer(IStatesDefinition) @@ -70,20 +71,35 @@ class ClassificationQualityCheckable(StatefulLoopsObject): def assign(self, relation): if not self.isRelevant(relation): return + versionable = IVersionable(self.context, None) if self.state in ('new', 'unclassified'): - self.doTransition('classify') + self.doTransitionWithVersions('classify', versionable) else: - self.doTransition('change_classification') + self.doTransitionWithVersions('change_classification', versionable) def deassign(self, relation): if not self.isRelevant(relation): return + versionable = IVersionable(self.context, None) if self.state in ('new', 'classified', 'verified'): - old = self.context.getParentRelations() - if len(old) > 2: # the hasType relation always remains - self.doTransition('change_classification') + parents = self.context.getParentRelations() + if len(parents) > 1: # the hasType relation always remains + self.doTransitionWithVersions('change_classification', versionable) else: - self.doTransition('remove_classification') + self.doTransitionWithVersions('remove_classification', versionable) + + def doTransitionWithVersions(self, transition, versionable): + self.doTransition(transition) + if versionable is None: + return + for v in versionable.versions.values(): + if v != self.context: + stf = component.getAdapter(v, IStateful, name=self.statesDefinition) + available = [t.name for t in stf.getAvailableTransitions()] + if transition in available: + stf.doTransition(transition) + #else: + # print '***', v.__name__, stf.state, transition, available def isRelevant(self, relation): """ Return True if the relation given is relevant for changing diff --git a/tests/setup.py b/tests/setup.py index 3b77193..c411368 100644 --- a/tests/setup.py +++ b/tests/setup.py @@ -28,6 +28,7 @@ from zope.publisher.interfaces.browser import IBrowserRequest, IBrowserView from zope.security.checker import Checker, defineChecker from cybertools.browser.controller import Controller +from cybertools.catalog.keyword import KeywordIndex from cybertools.composer.schema.factory import SchemaFactory from cybertools.composer.schema.field import FieldInstance, NumberFieldInstance from cybertools.composer.schema.field import DateFieldInstance, BooleanFieldInstance @@ -39,6 +40,7 @@ from cybertools.relation.interfaces import IRelation, IRelationRegistry from cybertools.relation.interfaces import IRelationInvalidatedEvent from cybertools.relation.registry import IndexableRelationAdapter from cybertools.relation.registry import invalidateRelations, removeRelation +from cybertools.stateful.interfaces import IStatefulIndexInfo from cybertools.typology.interfaces import IType from loops.base import Loops @@ -51,6 +53,7 @@ from loops.config.base import GlobalOptions, LoopsOptions from loops.interfaces import ILoopsObject, IIndexAttributes from loops.interfaces import IDocument, IFile, ITextDocument from loops.organize.memberinfo import MemberInfoProvider +from loops.organize.stateful.base import StatefulResourceIndexInfo, handleTransition from loops.query import QueryConcept from loops.query import QueryConcept from loops.resource import Resource, FileAdapter, TextDocumentAdapter @@ -150,8 +153,11 @@ class TestSite(object): catalog['loops_title'] = TextIndex('title', IIndexAttributes, True) catalog['loops_text'] = TextIndex('text', IIndexAttributes, True) catalog['loops_type'] = FieldIndex('tokenForSearch', IType, False) + catalog['loops_state'] = KeywordIndex('tokens', IStatefulIndexInfo, False) component.provideAdapter(ConceptIndexAttributes) component.provideAdapter(ResourceIndexAttributes) + component.provideAdapter(StatefulResourceIndexInfo) + component.provideHandler(handleTransition) loopsRoot = site['loops'] = Loops() setup = SetupManager(loopsRoot)