diff --git a/browser/common.py b/browser/common.py index 02d9902..3d51959 100644 --- a/browser/common.py +++ b/browser/common.py @@ -49,7 +49,7 @@ from zope.security import canAccess from zope.security.interfaces import ForbiddenAttribute, Unauthorized from zope.security.proxy import removeSecurityProxy from zope.traversing.browser import absoluteURL -from zope.traversing.api import getName, getParent +from zope.traversing.api import getName, getParent, traverse from cybertools.ajax.dojo import dojoMacroTemplate from cybertools.browser.view import GenericView @@ -70,7 +70,7 @@ from loops.organize.tracking import access from loops.resource import Resource from loops.security.common import checkPermission from loops.security.common import canAccessObject, canListObject, canWriteObject -from loops.type import ITypeConcept +from loops.type import ITypeConcept, LoopsTypeInfo from loops import util from loops.util import _, saveRequest from loops import version @@ -539,11 +539,29 @@ class BaseView(GenericView, I18NView): def conceptTypes(self): return util.KeywordVocabulary(self.listTypes(('concept',), ('hidden',))) + def parentTypesFromOtherSites(self): + result = [] + typeNames = self.typeOptions('foreign_parent_types') or [] + for path in self.typeOptions('foreign_parent_sites') or []: + site = traverse(self.loopsRoot, path, None) + if site is None: + continue + cm = site.getConceptManager() + for tname in typeNames: + t = cm.get(tname) + if t is not None: + type = LoopsTypeInfo(t) + type.isForeignReference = True + result.append(type) + return result + def listTypesForSearch(self, include=None, exclude=None, sortOn='title'): types = [dict(token=t.tokenForSearch, title=t.title) for t in ITypeManager(self.context).listTypes(include, exclude)] if sortOn: types.sort(key=lambda x: x[sortOn]) + for t in self.parentTypesFromOtherSites(): + types.append(dict(token=t.tokenForSearch, title=t.title)) return types def typesForSearch(self): diff --git a/expert/browser/search.py b/expert/browser/search.py index 3ffdfa1..7fd6cb0 100644 --- a/expert/browser/search.py +++ b/expert/browser/search.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2011 Helmut Merz helmutm@cy55.de +# Copyright (c) 2013 Helmut Merz helmutm@cy55.de # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -19,14 +19,12 @@ """ Definition of basic view classes and other browser related stuff for the loops.expert package. - -$Id$ """ from zope import interface, component from zope.app.pagetemplate import ViewPageTemplateFile from zope.cachedescriptors.property import Lazy -from zope.traversing.api import getName, getParent +from zope.traversing.api import getName, getParent, traverse from cybertools.browser.form import FormController from cybertools.stateful.interfaces import IStateful, IStatesDefinition @@ -150,12 +148,16 @@ class Search(ConceptView): if not isinstance(types, (list, tuple)): types = [types] for type in types: + site = self.loopsRoot + if type.startswith('/'): + parts = type.split(':') + site = traverse(self.loopsRoot, parts[0], site) result = self.executeQuery(title=title or None, type=type, exclude=('hidden',)) fv = FilterView(self.context, self.request) result = fv.apply(result) for o in result: - if o.getLoopsRoot() == self.loopsRoot: + if o.getLoopsRoot() == site: adObj = adapted(o, self.languageInfo) if filterMethod is not None and not filterMethod(adObj): continue diff --git a/expert/concept.py b/expert/concept.py index df0363c..4f3fbcb 100644 --- a/expert/concept.py +++ b/expert/concept.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2011 Helmut Merz helmutm@cy55.de +# Copyright (c) 2013 Helmut Merz helmutm@cy55.de # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,8 +18,6 @@ """ Query concepts management stuff. - -$Id$ """ from BTrees.IOBTree import IOBTree @@ -29,6 +27,7 @@ from zope.interface import Interface, Attribute, implements from zope.app.catalog.interfaces import ICatalog from zope.cachedescriptors.property import Lazy from zope.intid.interfaces import IIntIds +from zope.traversing.api import traverse from cybertools.typology.interfaces import IType from loops.common import AdapterBase @@ -66,6 +65,11 @@ class BaseQuery(object): return self.context.context.getLoopsRoot() def queryConcepts(self, title=None, type=None, **kw): + site = self.loopsRoot + if type.startswith('/'): + parts = type.split(':') + site = traverse(self.loopsRoot, parts[0], site) + type = 'loops:' + ':'.join(parts[1:]) if type.endswith('*'): start = type[:-1] end = start + '\x7f' @@ -76,7 +80,7 @@ class BaseQuery(object): result = cat.searchResults(loops_type=(start, end), loops_title=title) else: result = cat.searchResults(loops_type=(start, end)) - result = set(r for r in result if r.getLoopsRoot() == self.loopsRoot + result = set(r for r in result if r.getLoopsRoot() == site and canListObject(r)) if 'exclude' in kw: r1 = set() diff --git a/organize/stateful/browser.py b/organize/stateful/browser.py index a732752..31bfe7f 100644 --- a/organize/stateful/browser.py +++ b/organize/stateful/browser.py @@ -151,7 +151,7 @@ class ChangeState(ChangeStateBase, EditObject): def update(self): formData = self.request.form - # store data in context (unless field.nostore) + # store data in target object (unless field.nostore) self.object = self.target formState = self.instance.applyTemplate(data=formData) # TODO: check formState diff --git a/type.py b/type.py index 43e7c12..e948451 100644 --- a/type.py +++ b/type.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2012 Helmut Merz helmutm@cy55.de +# Copyright (c) 2013 Helmut Merz helmutm@cy55.de # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -26,7 +26,7 @@ from zope.interface import implements from zope.cachedescriptors.property import Lazy from zope.dottedname.resolve import resolve from zope.security.proxy import removeSecurityProxy -from zope.traversing.api import getName +from zope.traversing.api import getName, getPath from cybertools.typology.type import BaseType, TypeManager from cybertools.typology.interfaces import ITypeManager @@ -49,10 +49,15 @@ class LoopsType(BaseType): #document=Document) containerMapping = dict(concept='concepts', resource='resources') + isForeignReference = False + @Lazy def title(self): tp = self.typeProvider - return tp is None and u'Unknown Type' or tp.title + title = tp is None and u'Unknown Type' or tp.title + if self.isForeignReference: + title += (' (Site: %s)' % getName(self.root)) + return title @Lazy def token(self): @@ -63,7 +68,11 @@ class LoopsType(BaseType): def tokenForSearch(self): tp = self.typeProvider typeName = tp is None and 'unknown' or str(getName(tp)) - return ':'.join(('loops', self.qualifiers[0], typeName,)) + if self.isForeignReference: + root = getPath(self.root) + else: + root = 'loops' + return ':'.join((root, self.qualifiers[0], typeName,)) @Lazy def typeInterface(self):