# HG changeset patch # User Thierry Florac # Date 1521726742 -3600 # Node ID 04503227569d817b16fac696e7527fbba7b65e91 # Parent 828f9c9303cf5c7568752180c44270f0c6c10787 Added default factory adapters for shared tools and shared contents diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/blog/__init__.py --- a/src/pyams_content/shared/blog/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/blog/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -21,12 +21,14 @@ from pyams_content.component.theme.interfaces import IThemesTarget from pyams_content.features.preview.interfaces import IPreviewTarget from pyams_content.features.review.interfaces import IReviewTarget -from pyams_content.shared.blog.interfaces import IWfBlogPost, BLOG_CONTENT_TYPE, BLOG_CONTENT_NAME, IBlogPost +from pyams_content.shared.blog.interfaces import IWfBlogPost, BLOG_CONTENT_TYPE, BLOG_CONTENT_NAME, IBlogPost, \ + IWfBlogPostFactory from pyams_workflow.interfaces import IWorkflow, IWorkflowVersions, IWorkflowState # import packages -from pyams_content.shared.common import WfSharedContent, register_content_type, SharedContent -from zope.interface import implementer +from pyams_content.shared.common import WfSharedContent, register_content_type, SharedContent, IWfSharedContentFactory +from pyams_utils.adapter import adapter_config +from zope.interface import implementer, provider @implementer(IWfBlogPost, IParagraphContainerTarget, IThemesTarget, @@ -40,15 +42,19 @@ register_content_type(WfBlogPost) +@provider(IWfBlogPostFactory) @implementer(IBlogPost) class BlogPost(SharedContent): """Worfklow managed blog post class""" - content_class = WfBlogPost - def is_deletable(self): workflow = IWorkflow(self) for version in IWorkflowVersions(self).get_versions(): if IWorkflowState(version).state != workflow.initial_state: return False return True + + +@adapter_config(context=IWfBlogPostFactory, provides=IWfSharedContentFactory) +def BlogPostContentFactory(context): + return WfBlogPost diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/blog/interfaces/__init__.py --- a/src/pyams_content/shared/blog/interfaces/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/blog/interfaces/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -16,7 +16,7 @@ # import standard library # import interfaces -from pyams_content.shared.common.interfaces import ISharedSite, ISharedTool, IWfSharedContent, ISharedContent, \ +from pyams_content.shared.common.interfaces import ISharedSite, IBaseSharedTool, IWfSharedContent, ISharedContent, \ IDeletableElement from pyams_sequence.interfaces import ISequentialIdTarget from pyams_workflow.interfaces import IWorkflowPublicationSupport @@ -24,7 +24,7 @@ # import packages from zope.container.constraints import containers, contains -from zope.interface import Attribute +from zope.interface import Attribute, Interface from pyams_content import _ @@ -37,6 +37,10 @@ """Blog topic interface""" +class IWfBlogPostFactory(Interface): + """Blog post factory interface""" + + class IBlogPost(ISharedContent, IDeletableElement): """Workflow managed blog post interface""" @@ -50,9 +54,20 @@ contains('.IBlogFolder', '.IBlogPost') -class IBlogManager(ISharedSite, ISharedTool, IWorkflowPublicationSupport, IDeletableElement, ISequentialIdTarget): +class IBlogFolderFactory(Interface): + """Blog folder factory interface""" + + +class IBlogManager(ISharedSite, IBaseSharedTool, IWorkflowPublicationSupport, IDeletableElement, ISequentialIdTarget): """Blog manager interface""" contains(IBlogFolder) folder_factory = Attribute("Blog folder factory") + + topic_content_type = Attribute("Topic content type") + topic_content_factory = Attribute("Topic content factory") + + +class IBlogManagerFactory(Interface): + """Blog manager factory interface""" diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/blog/manager.py --- a/src/pyams_content/shared/blog/manager.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/blog/manager.py Thu Mar 22 14:52:22 2018 +0100 @@ -21,7 +21,9 @@ from pyams_content.component.theme.interfaces import IThemesManagerTarget from pyams_content.features.preview.interfaces import IPreviewTarget from pyams_content.reference.pictograms.interfaces import IPictogramManagerTarget -from pyams_content.shared.blog.interfaces import IBlogManager, BLOG_CONTENT_TYPE, IBlogFolder +from pyams_content.root.interfaces import ISiteRoot +from pyams_content.shared.blog.interfaces import IBlogManager, IBlogFolder, IBlogFolderFactory, IBlogManagerFactory +from pyams_content.shared.common.interfaces import ISharedContentFactory from pyams_portal.interfaces import IPortalContext from zope.annotation.interfaces import IAttributeAnnotatable from zope.component.interfaces import ISite @@ -29,8 +31,9 @@ # import packages from pyams_content.shared.blog import BlogPost -from pyams_content.shared.common.manager import SharedTool +from pyams_content.shared.common.manager import BaseSharedTool from pyams_skin.skin import UserSkinnableContent +from pyams_utils.adapter import adapter_config from pyams_utils.traversing import get_parent from pyramid.events import subscriber from zope.container.folder import Folder @@ -51,20 +54,29 @@ @implementer(IBlogManager, IParagraphFactorySettings, IThemesManagerTarget, IPictogramManagerTarget, IIllustrationTarget, IPortalContext, IPreviewTarget, IAttributeAnnotatable) -class BlogManager(SharedTool, UserSkinnableContent): +class BlogManager(Folder, BaseSharedTool, UserSkinnableContent): """Nlog manager class""" - folder_factory = BlogFolder - - shared_content_type = BLOG_CONTENT_TYPE - shared_content_factory = BlogPost - allowed_paragraphs = FieldProperty(IParagraphFactorySettings['allowed_paragraphs']) auto_created_paragraphs = FieldProperty(IParagraphFactorySettings['auto_created_paragraphs']) sequence_name = '' # use default sequence generator sequence_prefix = '' + @property + def folder_factory(self): + return IBlogFolderFactory(self, BlogFolder) + + @property + def topic_content_factory(self): + return ISharedContentFactory(self, None) + + @property + def topic_content_type(self): + factory = self.topic_content_factory + if factory is not None: + return factory.content_class.content_type + def is_deletable(self): for element in self.values(): if not element.is_deletable(): @@ -72,6 +84,21 @@ return True +@adapter_config(context=ISiteRoot, provides=IBlogManagerFactory) +def SiteRootBlogManagerFactory(context): + return BlogManager + + +@adapter_config(context=IBlogManager, provides=IBlogFolderFactory) +def BlogManagerFolderFactory(context): + return BlogFolder + + +@adapter_config(context=IBlogManager, provides=ISharedContentFactory) +def BlogManagerTopicFactory(context): + return BlogPost + + @subscriber(IObjectAddedEvent, context_selector=IBlogManager) def handle_added_blog_manager(event): """Register blog manager when added""" diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/blog/zmi/__init__.py --- a/src/pyams_content/shared/blog/zmi/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/blog/zmi/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -80,7 +80,7 @@ def add(self, wf_content): # create shared content - content = self.context.shared_content_factory() + content = self.context.topic_content_factory() self.request.registry.notify(ObjectCreatedEvent(content)) # check blog folders now = datetime.utcnow() diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/blog/zmi/manager.py --- a/src/pyams_content/shared/blog/zmi/manager.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/blog/zmi/manager.py Thu Mar 22 14:52:22 2018 +0100 @@ -16,11 +16,11 @@ # import standard library from pyams_content.interfaces import MANAGE_SITE_ROOT_PERMISSION, MANAGE_SITE_PERMISSION from pyams_content.root.interfaces import ISiteRoot -from pyams_content.shared.blog.interfaces import IBlogManager +from pyams_content.shared.blog.interfaces import IBlogManager, IBlogManagerFactory from pyams_content.skin.zmi.interfaces import ISiteTreeTable, IUserAddingsMenuLabel from pyams_i18n.interfaces import II18n, INegotiator from pyams_skin.interfaces.container import ITableElementEditor -from pyams_skin.interfaces.viewlet import IToolbarAddingMenu +from pyams_skin.interfaces.viewlet import IToolbarAddingMenu, ITableItemColumnActionsMenu from pyams_skin.layer import IPyAMSLayer from pyams_workflow.interfaces import IWorkflowPublicationInfo from pyams_zmi.interfaces.menu import IPropertiesMenu @@ -30,6 +30,7 @@ from z3c.form.interfaces import IDataExtractedEvent # import packages +from pyams_content.shared.blog.manager import BlogManager from pyams_form.form import AJAXAddForm, AJAXEditForm from pyams_pagelet.pagelet import pagelet_config from pyams_skin.table import DefaultElementEditorAdapter @@ -91,9 +92,10 @@ def create(self, data): factory = self.request.registry.settings.get('pyams_content.config.blog_factory') - if factory is None: - factory = 'pyams_content.shared.blog.manager.BlogManager' - factory = DottedNameResolver().resolve(factory) + if factory: + factory = DottedNameResolver().resolve(factory) + else: + factory = IBlogManagerFactory(self.context, BlogManager) return factory() def add(self, object): @@ -141,8 +143,20 @@ # Blog manager publication views # +@viewlet_config(name='workflow-publication.menu', context=IBlogManager, layer=IPyAMSLayer, view=ISiteTreeTable, + manager=ITableItemColumnActionsMenu, permission=MANAGE_SITE_PERMISSION, weight=210) +class BlogManagerTableItemWorkflowPublicationMenu(ToolbarMenuItem): + """Blog manager tree item workflow publication menu""" + + label = _("Publication dates...") + label_css_class = 'fa fa-fw fa-eye' + url = 'workflow-publication.html' + modal_target = True + stop_propagation = True + + @viewlet_config(name='workflow-publication.menu', context=IBlogManager, layer=IAdminLayer, manager=IPropertiesMenu, - permission=MANAGE_SITE_PERMISSION, weight=2) + permission=MANAGE_SITE_PERMISSION, weight=210) class BlogManagerWorkflowPublicationMenu(MenuItem): """Blog manager workflow publication menu""" diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/common/__init__.py --- a/src/pyams_content/shared/common/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/common/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -21,7 +21,7 @@ from pyams_content.features.checker.interfaces import IContentChecker, MISSING_VALUE, MISSING_LANG_VALUE, ERROR_VALUE from pyams_content.features.review.interfaces import IReviewComments from pyams_content.shared.common.interfaces import IWfSharedContent, IWfSharedContentRoles, ISharedContent, \ - IBaseSharedTool, ISharedSite + IBaseSharedTool, ISharedSite, IWfSharedContentFactory from pyams_i18n.interfaces import II18nManager, II18n from pyams_security.interfaces import IDefaultProtectionPolicy from pyams_sequence.interfaces import ISequentialIdTarget, ISequentialIdInfo @@ -41,6 +41,7 @@ from pyams_security.utility import get_principal from pyams_utils.adapter import adapter_config, ContextAdapter from pyams_utils.date import format_datetime +from pyams_utils.property import classproperty, classproperty_support from pyams_utils.registry import query_utility, get_utilities_for from pyams_utils.request import query_request, check_request from pyams_utils.timezone import tztime @@ -266,6 +267,7 @@ # Main shared content class and adapters # +@classproperty_support @implementer(ISharedContent, ISequentialIdTarget) class SharedContent(Persistent, Contained): """Workflow managed shared data""" @@ -275,6 +277,10 @@ sequence_name = '' # use default sequence generator sequence_prefix = '' + @classproperty + def content_class(cls): + return IWfSharedContentFactory(cls, None) + @property def workflow_name(self): return get_parent(self, IBaseSharedTool).shared_content_workflow diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/common/interfaces/__init__.py --- a/src/pyams_content/shared/common/interfaces/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/common/interfaces/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -148,6 +148,10 @@ required=False) +class IWfSharedContentFactory(Interface): + """Shared content factory interface""" + + class IWfSharedContentRoles(Interface): """Shared content roles""" @@ -186,6 +190,10 @@ """Workflow managed shared content interface""" +class ISharedContentFactory(Interface): + """Workflow managed shared content factory interface""" + + # # Shared tool manager security restrictions # diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/common/manager.py --- a/src/pyams_content/shared/common/manager.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/common/manager.py Thu Mar 22 14:52:22 2018 +0100 @@ -17,7 +17,8 @@ # import interfaces from pyams_content.interfaces import WEBMASTER_ROLE, PILOT_ROLE, MANAGER_ROLE, CONTRIBUTOR_ROLE -from pyams_content.shared.common.interfaces import ISharedToolContainer, IBaseSharedTool, ISharedTool, ISharedToolRoles +from pyams_content.shared.common.interfaces import ISharedToolContainer, IBaseSharedTool, ISharedTool, ISharedToolRoles, \ + ISharedContentFactory from pyams_security.interfaces import IDefaultProtectionPolicy from pyams_workflow.interfaces import IWorkflow from zope.annotation.interfaces import IAttributeAnnotatable @@ -64,8 +65,15 @@ class SharedTool(Folder, BaseSharedTool): """Shared tool class""" - shared_content_type = None - shared_content_factory = None + @property + def shared_content_factory(self): + return ISharedContentFactory(self, None) + + @property + def shared_content_type(self): + factory = self.shared_content_factory + if factory is not None: + return factory.content_class.content_type @adapter_config(context=IBaseSharedTool, provides=IWorkflow) diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/common/review.py --- a/src/pyams_content/shared/common/review.py Thu Mar 22 14:50:32 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -# -# Copyright (c) 2008-2015 Thierry Florac -# All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# - -__docformat__ = 'restructuredtext' - - -# import standard library - -# import interfaces - -# import packages - -# imports for backward compatibility: module moved to pyams_content.features.review !! -from pyams_content.features.review import ReviewComment, ReviewCommentsContainer diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/form/__init__.py --- a/src/pyams_content/shared/form/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/form/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -20,13 +20,14 @@ from pyams_content.features.preview.interfaces import IPreviewTarget from pyams_content.features.review.interfaces import IReviewTarget from pyams_content.shared.form.interfaces import IWfForm, IForm, FORM_CONTENT_TYPE, FORM_CONTENT_NAME, \ - IFormFieldContainerTarget, IFormHandler, IFormFieldContainer + IFormFieldContainerTarget, IFormHandler, IFormFieldContainer, IWfFormFactory # import packages -from pyams_content.shared.common import WfSharedContent, SharedContent, register_content_type, WfSharedContentChecker +from pyams_content.shared.common import WfSharedContent, SharedContent, register_content_type, WfSharedContentChecker, \ + IWfSharedContentFactory from pyams_utils.adapter import adapter_config from pyams_utils.registry import get_global_registry -from zope.interface import implementer, alsoProvides, noLongerProvides +from zope.interface import implementer, provider, alsoProvides, noLongerProvides from zope.schema.fieldproperty import FieldProperty from pyams_content import _ @@ -76,11 +77,15 @@ register_content_type(WfForm) +@provider(IWfFormFactory) @implementer(IForm) class Form(SharedContent): """Workflow managed form class""" - content_class = WfForm + +@adapter_config(context=IWfFormFactory, provides=IWfSharedContentFactory) +def FormContentFactory(context): + return WfForm @adapter_config(name='properties', context=IWfForm, provides=IContentChecker) diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/form/interfaces/__init__.py --- a/src/pyams_content/shared/form/interfaces/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/form/interfaces/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -37,7 +37,11 @@ class IFormsManager(ISharedTool): - """Formq manager interface""" + """Forms manager interface""" + + +class IFormsManagerFactory(Interface): + """Forms manager factory interface""" class IFormField(IContained): @@ -142,6 +146,10 @@ """Get form handler utility""" +class IWfFormFactory(Interface): + """Form factory interface""" + + class IForm(ISharedContent): """Workflow managed form interface""" diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/form/manager.py --- a/src/pyams_content/shared/form/manager.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/form/manager.py Thu Mar 22 14:52:22 2018 +0100 @@ -16,7 +16,8 @@ # import standard library # import interfaces -from pyams_content.shared.form.interfaces import IFormsManager, FORM_CONTENT_TYPE +from pyams_content.shared.common.interfaces import ISharedContentFactory +from pyams_content.shared.form.interfaces import IFormsManager, FORM_CONTENT_TYPE, IFormsManagerFactory from zope.annotation.interfaces import IAttributeAnnotatable from zope.component.interfaces import ISite from zope.lifecycleevent.interfaces import IObjectAddedEvent @@ -24,6 +25,8 @@ # import packages from pyams_content.shared.common.manager import SharedTool from pyams_content.shared.form import Form +from pyams_utils.adapter import adapter_config +from pyams_utils.registry import utility_config from pyams_utils.traversing import get_parent from pyramid.events import subscriber from zope.interface import implementer @@ -34,7 +37,19 @@ """Forms manager class""" shared_content_type = FORM_CONTENT_TYPE - shared_content_factory = Form + + +@utility_config(provides=IFormsManagerFactory) +class FormsManagerFactory(object): + """Defautl forms manager factory""" + + def __new__(cls): + return FormsManager + + +@adapter_config(context=IFormsManager, provides=ISharedContentFactory) +def FormsManagerContentFactory(context): + return Form @subscriber(IObjectAddedEvent, context_selector=IFormsManager) diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/imagemap/__init__.py --- a/src/pyams_content/shared/imagemap/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/imagemap/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -25,19 +25,20 @@ from pyams_content.features.preview.interfaces import IPreviewTarget from pyams_content.features.review.interfaces import IReviewTarget from pyams_content.shared.imagemap.interfaces import IMAGEMAP_CONTENT_TYPE, IMAGEMAP_CONTENT_NAME, \ - IWfImageMap, IImageMap, IImageMapArea + IWfImageMap, IImageMap, IImageMapArea, IWfImageMapFactory from pyams_i18n.interfaces import II18n, II18nManager from z3c.form.interfaces import NOT_CHANGED from zope.location.interfaces import ISublocations from zope.traversing.interfaces import ITraversable # import packages -from pyams_content.shared.common import WfSharedContent, register_content_type, SharedContent, WfSharedContentChecker +from pyams_content.shared.common import WfSharedContent, register_content_type, SharedContent, WfSharedContentChecker, \ + IWfSharedContentFactory from pyams_i18n.property import I18nFileProperty from pyams_utils.adapter import adapter_config, ContextAdapter from pyramid.threadlocal import get_current_registry from zope.container.contained import Contained -from zope.interface import implementer +from zope.interface import implementer, provider from zope.lifecycleevent import ObjectModifiedEvent from zope.location import locate from zope.schema.fieldproperty import FieldProperty @@ -102,11 +103,15 @@ register_content_type(WfImageMap) +@provider(IWfImageMapFactory) @implementer(IImageMap) class ImageMap(SharedContent): """Workflow managed image map class""" - content_class = WfImageMap + +@adapter_config(context=IWfImageMapFactory, provides=IWfSharedContentFactory) +def ImageMapContentFactory(context): + return WfImageMap @adapter_config(name='areas', context=IWfImageMap, provides=ITraversable) diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/imagemap/interfaces/__init__.py --- a/src/pyams_content/shared/imagemap/interfaces/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/imagemap/interfaces/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -25,6 +25,7 @@ from pyams_i18n.schema import I18nTextLineField, I18nImageField from pyams_sequence.schema import InternalReference from pyams_utils.schema import PersistentDict +from zope.interface import Interface from zope.schema import Object, Choice from pyams_content import _ @@ -38,6 +39,10 @@ """Image maps manager interface""" +class IImageMapManagerFactory(Interface): + """Image maps manager factory interface""" + + class IImageMapArea(IAttributeAnnotatable): """Image map area interface""" @@ -71,6 +76,10 @@ """Get association for given area""" +class IWfImageMapFactory(Interface): + """Image map factory interface""" + + class IImageMap(ISharedContent): """Workflow managed image map interface""" diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/imagemap/manager.py --- a/src/pyams_content/shared/imagemap/manager.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/imagemap/manager.py Thu Mar 22 14:52:22 2018 +0100 @@ -16,13 +16,16 @@ # import standard library # import interfaces -from pyams_content.shared.imagemap.interfaces import IImageMapManager, IMAGEMAP_CONTENT_TYPE +from pyams_content.shared.common.interfaces import ISharedContentFactory +from pyams_content.shared.imagemap.interfaces import IImageMapManager, IMAGEMAP_CONTENT_TYPE, IImageMapManagerFactory from zope.annotation.interfaces import IAttributeAnnotatable from zope.lifecycleevent.interfaces import IObjectAddedEvent # import packages from pyams_content.shared.common.manager import SharedTool from pyams_content.shared.imagemap import ImageMap +from pyams_utils.adapter import adapter_config +from pyams_utils.registry import utility_config from pyams_utils.traversing import get_parent from pyramid.events import subscriber from zope.component.interfaces import ISite @@ -34,7 +37,19 @@ """Image maps manager class""" shared_content_type = IMAGEMAP_CONTENT_TYPE - shared_content_factory = ImageMap + + +@utility_config(provides=IImageMapManagerFactory) +class ImageMapsManagerFactory(object): + """Default image maps manager factory""" + + def __new__(cls): + return ImageMapsManager + + +@adapter_config(context=IImageMapManager, provides=ISharedContentFactory) +def ImageMapsManagerContentFactory(context): + return ImageMap @subscriber(IObjectAddedEvent, context_selector=IImageMapManager) diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/logo/__init__.py --- a/src/pyams_content/shared/logo/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/logo/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -17,14 +17,15 @@ # import interfaces from pyams_content.features.checker.interfaces import IContentChecker, MISSING_VALUE -from pyams_content.shared.logo.interfaces import IWfLogo, LOGO_CONTENT_TYPE, LOGO_CONTENT_NAME, ILogo +from pyams_content.shared.logo.interfaces import IWfLogo, LOGO_CONTENT_TYPE, LOGO_CONTENT_NAME, ILogo, IWfLogoFactory from pyams_content.features.review import IReviewTarget # import packages -from pyams_content.shared.common import WfSharedContent, register_content_type, SharedContent, WfSharedContentChecker +from pyams_content.shared.common import WfSharedContent, register_content_type, SharedContent, WfSharedContentChecker, \ + IWfSharedContentFactory from pyams_file.property import FileProperty from pyams_utils.adapter import adapter_config -from zope.interface import implementer +from zope.interface import implementer, provider from zope.schema.fieldproperty import FieldProperty from pyams_content import _ @@ -40,15 +41,18 @@ image = FileProperty(IWfLogo['image']) url = FieldProperty(IWfLogo['url']) - register_content_type(WfLogo) +@provider(IWfLogoFactory) @implementer(ILogo) class Logo(SharedContent): """WOrkflow managed logo persistent class""" - content_class = WfLogo + +@adapter_config(context=IWfLogoFactory, provides=IWfSharedContentFactory) +def LogoContentFactory(context): + return WfLogo @adapter_config(name='properties', context=IWfLogo, provides=IContentChecker) diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/logo/interfaces/__init__.py --- a/src/pyams_content/shared/logo/interfaces/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/logo/interfaces/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -23,6 +23,7 @@ # import packages from pyams_file.schema import ImageField from pyams_sequence.schema import InternalReferencesList +from zope.interface import Interface from zope.schema import URI, Choice from pyams_content import _ @@ -36,6 +37,10 @@ """Logos manager interface""" +class ILogosManagerFactory(Interface): + """Logos manager factory interface""" + + class IWfLogo(IWfSharedContent): """Logo interface""" @@ -48,6 +53,10 @@ required=False) +class IWfLogoFactory(Interface): + """Logo factory interface""" + + class ILogo(ISharedContent): """Workflow managed logo interface""" diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/logo/manager.py --- a/src/pyams_content/shared/logo/manager.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/logo/manager.py Thu Mar 22 14:52:22 2018 +0100 @@ -16,7 +16,8 @@ # import standard library # import interfaces -from pyams_content.shared.logo.interfaces import ILogosManager +from pyams_content.shared.common.interfaces import ISharedContentFactory +from pyams_content.shared.logo.interfaces import ILogosManager, ILogosManagerFactory from zope.annotation import IAttributeAnnotatable from zope.component.interfaces import ISite from zope.lifecycleevent import IObjectAddedEvent @@ -24,6 +25,8 @@ # import packages from pyams_content.shared.common.manager import SharedTool from pyams_content.shared.logo import LOGO_CONTENT_TYPE, Logo +from pyams_utils.adapter import adapter_config +from pyams_utils.registry import utility_config from pyams_utils.traversing import get_parent from pyramid.events import subscriber from zope.interface import implementer @@ -34,7 +37,20 @@ """Logos manager class""" shared_content_type = LOGO_CONTENT_TYPE - shared_content_factory = Logo + + +@utility_config(provides=ILogosManagerFactory) +class LogosManagerFactory(object): + """Default logos manager factory""" + + def __new__(cls): + return LogosManager + + +@adapter_config(context=ILogosManager, provides=ISharedContentFactory) +def LogosManagerContentFactory(context): + """Logos manager content factory""" + return Logo @subscriber(IObjectAddedEvent, context_selector=ILogosManager) diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/news/__init__.py --- a/src/pyams_content/shared/news/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/news/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -21,11 +21,13 @@ from pyams_content.component.theme.interfaces import IThemesTarget from pyams_content.features.preview.interfaces import IPreviewTarget from pyams_content.features.review.interfaces import IReviewTarget -from pyams_content.shared.news.interfaces import INewsEvent, IWfNewsEvent, NEWS_CONTENT_TYPE, NEWS_CONTENT_NAME +from pyams_content.shared.news.interfaces import INewsEvent, IWfNewsEvent, NEWS_CONTENT_TYPE, NEWS_CONTENT_NAME, \ + IWfNewsEventFactory # import packages -from pyams_content.shared.common import SharedContent, WfSharedContent, register_content_type -from zope.interface import implementer +from pyams_content.shared.common import SharedContent, WfSharedContent, register_content_type, IWfSharedContentFactory +from pyams_utils.adapter import adapter_config +from zope.interface import implementer, provider @implementer(IWfNewsEvent, IIllustrationTarget, IParagraphContainerTarget, IThemesTarget, @@ -39,8 +41,12 @@ register_content_type(WfNewsEvent) +@provider(IWfNewsEventFactory) @implementer(INewsEvent) class NewsEvent(SharedContent): """Workflow managed news event class""" - content_class = WfNewsEvent + +@adapter_config(context=IWfNewsEventFactory, provides=IWfSharedContentFactory) +def NewsEventContentFactory(context): + return WfNewsEvent diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/news/interfaces/__init__.py --- a/src/pyams_content/shared/news/interfaces/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/news/interfaces/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -19,6 +19,7 @@ from pyams_content.shared.common.interfaces import ISharedTool, IWfSharedContent, ISharedContent # import packages +from zope.interface import Interface from pyams_content import _ @@ -31,9 +32,17 @@ """News manager interface""" +class INewsManagerFactory(Interface): + """News manager factory interface""" + + class IWfNewsEvent(IWfSharedContent): """News event interface""" +class IWfNewsEventFactory(Interface): + """News event parent interface""" + + class INewsEvent(ISharedContent): """Workflow managed news event interface""" diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/news/manager.py --- a/src/pyams_content/shared/news/manager.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/news/manager.py Thu Mar 22 14:52:22 2018 +0100 @@ -19,13 +19,16 @@ from pyams_content.component.paragraph.interfaces import IParagraphFactorySettings from pyams_content.component.theme.interfaces import IThemesManagerTarget from pyams_content.reference.pictograms.interfaces import IPictogramManagerTarget -from pyams_content.shared.news.interfaces import INewsManager, NEWS_CONTENT_TYPE +from pyams_content.shared.common.interfaces import ISharedContentFactory +from pyams_content.shared.news.interfaces import INewsManager, NEWS_CONTENT_TYPE, INewsManagerFactory from zope.component.interfaces import ISite from zope.lifecycleevent.interfaces import IObjectAddedEvent # import packages from pyams_content.shared.common.manager import SharedTool from pyams_content.shared.news import NewsEvent +from pyams_utils.adapter import adapter_config +from pyams_utils.registry import utility_config from pyams_utils.traversing import get_parent from pyramid.events import subscriber from zope.interface import implementer @@ -37,12 +40,24 @@ """News manager class""" shared_content_type = NEWS_CONTENT_TYPE - shared_content_factory = NewsEvent allowed_paragraphs = FieldProperty(IParagraphFactorySettings['allowed_paragraphs']) auto_created_paragraphs = FieldProperty(IParagraphFactorySettings['auto_created_paragraphs']) +@utility_config(provides=INewsManagerFactory) +class NewsManagerFactory(object): + """Default news manager factory""" + + def __new__(cls): + return NewsManager + + +@adapter_config(context=INewsManager, provides=ISharedContentFactory) +def NewsManagerContentFactory(context): + return NewsEvent + + @subscriber(IObjectAddedEvent, context_selector=INewsManager) def handle_added_news_manager(event): """Register news manager when added""" diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/site/__init__.py --- a/src/pyams_content/shared/site/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/site/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -24,10 +24,11 @@ from pyams_workflow.interfaces import IWorkflow, IWorkflowVersions, IWorkflowState # import packages -from pyams_content.shared.common import SharedContent, WfSharedContent, register_content_type +from pyams_content.shared.common import SharedContent, WfSharedContent, register_content_type, IWfSharedContentFactory from pyams_content.shared.site.interfaces import ISiteContainer, ISiteFolder, ITopic, IWfTopic, TOPIC_CONTENT_NAME, \ - TOPIC_CONTENT_TYPE -from zope.interface import implementer + TOPIC_CONTENT_TYPE, IWfTopicFactory +from pyams_utils.adapter import adapter_config +from zope.interface import implementer, provider @implementer(IWfTopic, IParagraphContainerTarget, IThemesTarget, @@ -41,15 +42,19 @@ register_content_type(WfTopic) +@provider(IWfTopicFactory) @implementer(ITopic) class Topic(SharedContent): """WOrkflow managed topic class""" - content_class = WfTopic - def is_deletable(self): workflow = IWorkflow(self) for version in IWorkflowVersions(self).get_versions(): if IWorkflowState(version).state != workflow.initial_state: return False return True + + +@adapter_config(context=IWfTopicFactory, provides=IWfSharedContentFactory) +def TopicContentFactory(context): + return WfTopic diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/site/container.py --- a/src/pyams_content/shared/site/container.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/site/container.py Thu Mar 22 14:52:22 2018 +0100 @@ -17,11 +17,14 @@ import json # import interfaces +from pyams_content.shared.common.interfaces import ISharedContentFactory from pyams_content.shared.site.interfaces import ISiteContainer, ISiteFolder from pyams_i18n.interfaces import II18n from zope.intid.interfaces import IIntIds # import packages +from pyams_content.shared.site import Topic +from pyams_utils.adapter import adapter_config from pyams_utils.registry import get_utility from pyams_utils.request import query_request from pyramid.location import lineage @@ -82,3 +85,8 @@ container = container.__parent__ return json.dumps(items) + + +@adapter_config(context=ISiteContainer, provides=ISharedContentFactory) +def SiteContainerTopicFactory(context): + return Topic diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/site/interfaces/__init__.py --- a/src/pyams_content/shared/site/interfaces/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/site/interfaces/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -26,7 +26,7 @@ IBaseContentManagerRoles, IBaseSharedTool, IDeletableElement from pyams_i18n.schema import I18nTextLineField from zope.container.constraints import containers, contains -from zope.interface import Attribute +from zope.interface import Interface, Attribute from zope.schema import Text, Bool from pyams_content import _ @@ -58,6 +58,10 @@ required=False) +class ISiteFolderFactory(Interface): + """Site folder factory interface""" + + class ISiteFolderRoles(IBaseContentManagerRoles): """Site folder roles interface""" @@ -73,6 +77,10 @@ topic_content_factory = Attribute("Topic content factory") +class ISiteManagerFactory(Interface): + """Site manager factory interface""" + + TOPIC_CONTENT_TYPE = 'topic' TOPIC_CONTENT_NAME = _("Topic") @@ -81,6 +89,10 @@ """Topic interface""" +class IWfTopicFactory(Interface): + """Topic factory interface""" + + class ITopic(ISharedContent, ISiteElement): """Workflow managed topic interface""" diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/site/manager.py --- a/src/pyams_content/shared/site/manager.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/site/manager.py Thu Mar 22 14:52:22 2018 +0100 @@ -22,7 +22,9 @@ from pyams_content.features.preview.interfaces import IPreviewTarget from pyams_content.interfaces import MANAGE_SITE_PERMISSION from pyams_content.reference.pictograms.interfaces import IPictogramManagerTarget -from pyams_content.shared.site.interfaces import ISiteManager, TOPIC_CONTENT_TYPE +from pyams_content.root.interfaces import ISiteRoot +from pyams_content.shared.common.interfaces import ISharedContentFactory +from pyams_content.shared.site.interfaces import ISiteManager, ISiteManagerFactory, ISiteFolderFactory from pyams_form.interfaces.form import IFormContextPermissionChecker from pyams_i18n.interfaces import II18n from pyams_portal.interfaces import IPortalContext @@ -32,7 +34,7 @@ # import packages from pyams_content.shared.common.manager import BaseSharedTool -from pyams_content.shared.site import Topic +from pyams_content.shared.site import Topic, ISiteContainer from pyams_content.shared.site.container import SiteContainerMixin from pyams_content.shared.site.folder import SiteFolder from pyams_skin.skin import UserSkinnableContent @@ -53,17 +55,26 @@ class SiteManager(SiteContainerMixin, OrderedContainer, BaseSharedTool, UserSkinnableContent): """Site manager persistent class""" - folder_factory = SiteFolder - - topic_content_type = TOPIC_CONTENT_TYPE - topic_content_factory = Topic - allowed_paragraphs = FieldProperty(IParagraphFactorySettings['allowed_paragraphs']) auto_created_paragraphs = FieldProperty(IParagraphFactorySettings['auto_created_paragraphs']) sequence_name = '' # use default sequence generator sequence_prefix = '' + @property + def folder_factory(self): + return ISiteFolderFactory(self, SiteFolder) + + @property + def topic_content_factory(self): + return ISharedContentFactory(self, None) + + @property + def topic_content_type(self): + factory = self.topic_content_factory + if factory is not None: + return factory.content_class.content_type + def is_deletable(self): for element in self.values(): if not element.is_deletable(): @@ -71,6 +82,21 @@ return True +@adapter_config(context=ISiteRoot, provides=ISiteManagerFactory) +def SiteRootSiteManagerFactory(context): + return SiteManager + + +@adapter_config(context=ISiteManager, provides=ISiteFolderFactory) +def SiteManagerFolderFactory(context): + return SiteFolder + + +@adapter_config(context=ISiteContainer, provides=ISharedContentFactory) +def SiteManagerSharedContentFactory(context): + return Topic + + @subscriber(IObjectAddedEvent, context_selector=ISiteManager) def handle_added_site_manager(event): """Register site manager when added""" diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/site/zmi/__init__.py --- a/src/pyams_content/shared/site/zmi/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/site/zmi/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -36,6 +36,8 @@ from pyams_utils.traversing import get_parent from pyams_utils.url import absolute_url from pyams_viewlet.viewlet import viewlet_config +from pyramid.decorator import reify +from pyramid.path import DottedNameResolver from pyramid.view import view_config from z3c.form import field from zope.interface import Interface @@ -85,11 +87,22 @@ if 'parent' in self.widgets: self.widgets['parent'].permission = CREATE_CONTENT_PERMISSION + @reify + def content_factory(self): + registry = self.request.registry + factory = registry.settings.get('pyams_content.config.topic_factory') + if factory: + factory = DottedNameResolver().resolve(factory) + else: + manager = get_parent(self.context, ISiteManager) + factory = manager.topic_content_factory + return factory + def create(self, data): - manager = get_parent(self.context, ISiteManager) - return manager.topic_content_factory.content_class() + return self.content_factory.content_class() def update_content(self, content, data): + data = data.get(self, data) # initialize content fields content.title = data['title'] content.short_name = content.title.copy() @@ -103,8 +116,7 @@ languages = II18nManager(parent).languages if languages: II18nManager(content).languages = languages.copy() - manager = get_parent(parent, ISiteManager) - wf_parent = manager.topic_content_factory() + wf_parent = self.content_factory() self.request.registry.notify(ObjectCreatedEvent(wf_parent)) uuid = str(uuid4()) parent[uuid] = wf_parent diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/site/zmi/folder.py --- a/src/pyams_content/shared/site/zmi/folder.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/site/zmi/folder.py Thu Mar 22 14:52:22 2018 +0100 @@ -38,6 +38,7 @@ from pyams_viewlet.viewlet import viewlet_config from pyams_zmi.form import AdminDialogAddForm from pyramid.events import subscriber +from pyramid.path import DottedNameResolver from pyramid.view import view_config from z3c.form import field from zope.interface import Interface, Invalid @@ -99,10 +100,18 @@ self.widgets['notepad'].widget_css_class = 'textarea' def create(self, data): - manager = get_parent(self.context, ISiteManager) - return manager.folder_factory() + registry = self.request.registry + factory = registry.settings.get('pyams_content.config.folder_factory') + if factory: + factory = DottedNameResolver().resolve(factory) + else: + manager = get_parent(self.context, ISiteManager) + factory = manager.folder_factory + return factory() def update_content(self, content, data): + data = data.get(self, data) + # initialize content.title = data['title'] content.short_name = data['title'] content.notepad = data['notepad'] diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/site/zmi/manager.py --- a/src/pyams_content/shared/site/zmi/manager.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/site/zmi/manager.py Thu Mar 22 14:52:22 2018 +0100 @@ -18,7 +18,7 @@ # import interfaces from pyams_content.interfaces import MANAGE_SITE_ROOT_PERMISSION from pyams_content.root.interfaces import ISiteRoot -from pyams_content.shared.site.interfaces import ISiteManager +from pyams_content.shared.site.interfaces import ISiteManager, ISiteManagerFactory from pyams_content.skin.zmi.interfaces import ISiteTreeTable, IUserAddingsMenuLabel from pyams_i18n.interfaces import II18n, INegotiator from pyams_skin.interfaces.container import ITableElementEditor @@ -29,6 +29,7 @@ # import packages from pyams_content.shared.site import WfTopic +from pyams_content.shared.site.manager import SiteManager from pyams_form.form import AJAXAddForm from pyams_pagelet.pagelet import pagelet_config from pyams_skin.table import DefaultElementEditorAdapter @@ -66,9 +67,9 @@ @property def label(self): - return '{content} ({blog})'.format( + return '{content} ({site})'.format( content=self.request.localizer.translate(WfTopic.content_name), - blog=II18n(self.context).query_attribute('title', request=self.request)) + site=II18n(self.context).query_attribute('title', request=self.request)) @viewlet_config(name='add-site-manager.menu', context=ISiteRoot, layer=IAdminLayer, @@ -97,9 +98,10 @@ def create(self, data): factory = self.request.registry.settings.get('pyams_content.config.site_factory') - if factory is None: - factory = 'pyams_content.shared.site.manager.SiteManager' - factory = DottedNameResolver().resolve(factory) + if factory: + factory = DottedNameResolver().resolve(factory) + else: + factory = ISiteManagerFactory(self.context, SiteManager) return factory() def add(self, object): diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/view/__init__.py --- a/src/pyams_content/shared/view/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/view/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -23,8 +23,8 @@ from hypatia.interfaces import ICatalog from pyams_content.features.preview.interfaces import IPreviewTarget from pyams_content.features.review.interfaces import IReviewTarget -from pyams_content.shared.view.interfaces import IView, IWfView, IViewQuery, IViewQueryParamsExtension, \ - IViewQueryFilterExtension, VIEW_CONTENT_TYPE, VIEW_CONTENT_NAME, IViewSettings +from pyams_content.shared.view.interfaces import IView, IWfView, IWfViewFactory, IViewQuery, \ + IViewQueryParamsExtension, IViewQueryFilterExtension, VIEW_CONTENT_TYPE, VIEW_CONTENT_NAME, IViewSettings from zope.intid.interfaces import IIntIds from zope.lifecycleevent.interfaces import IObjectModifiedEvent @@ -33,7 +33,7 @@ from hypatia.query import Any, Gt, Lt from pyams_cache.beaker import get_cache from pyams_catalog.query import CatalogResultSet, or_ -from pyams_content.shared.common import WfSharedContent, register_content_type, SharedContent +from pyams_content.shared.common import WfSharedContent, register_content_type, SharedContent, IWfSharedContentFactory from pyams_utils.adapter import adapter_config, ContextAdapter from pyams_utils.list import unique from pyams_utils.registry import get_utility, get_global_registry @@ -41,7 +41,7 @@ from pyams_workflow.interfaces import IWorkflow from pyramid.events import subscriber from pyramid.threadlocal import get_current_registry -from zope.interface import implementer +from zope.interface import implementer, provider from zope.schema.fieldproperty import FieldProperty @@ -111,11 +111,15 @@ register_content_type(WfView) +@provider(IWfViewFactory) @implementer(IView) class View(SharedContent): """Workflow managed view class""" - content_class = WfView + +@adapter_config(context=IWfViewFactory, provides=IWfSharedContentFactory) +def ViewContentFactory(context): + return WfView @adapter_config(context=IWfView, provides=IViewQuery) diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/view/interfaces/__init__.py --- a/src/pyams_content/shared/view/interfaces/__init__.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/view/interfaces/__init__.py Thu Mar 22 14:52:22 2018 +0100 @@ -50,6 +50,10 @@ """Views manager interface""" +class IViewsManagerFactory(Interface): + """Views manager factory interface""" + + class IWfView(IWfSharedContent): """View interface""" @@ -87,6 +91,10 @@ """Get results of catalog query""" +class IWfViewFactory(Interface): + """View factory interface""" + + class IView(ISharedContent): """Workflow managed view interface""" diff -r 828f9c9303cf -r 04503227569d src/pyams_content/shared/view/manager.py --- a/src/pyams_content/shared/view/manager.py Thu Mar 22 14:50:32 2018 +0100 +++ b/src/pyams_content/shared/view/manager.py Thu Mar 22 14:52:22 2018 +0100 @@ -17,7 +17,8 @@ # import interfaces from pyams_content.component.theme.interfaces import IThemesManagerTarget -from pyams_content.shared.view.interfaces import IViewsManager, VIEW_CONTENT_TYPE +from pyams_content.shared.common.interfaces import ISharedContentFactory +from pyams_content.shared.view.interfaces import IViewsManager, VIEW_CONTENT_TYPE, IViewsManagerFactory from zope.annotation.interfaces import IAttributeAnnotatable from zope.component.interfaces import ISite from zope.lifecycleevent.interfaces import IObjectAddedEvent @@ -25,6 +26,8 @@ # import packages from pyams_content.shared.common.manager import SharedTool from pyams_content.shared.view import View +from pyams_utils.adapter import adapter_config +from pyams_utils.registry import utility_config from pyams_utils.traversing import get_parent from pyramid.events import subscriber from zope.interface import implementer @@ -35,7 +38,20 @@ """Views manager class""" shared_content_type = VIEW_CONTENT_TYPE - shared_content_factory = View + + +@utility_config(provides=IViewsManagerFactory) +class ViewsManagerFactory(object): + """Default views manager factory""" + + def __new__(cls): + return ViewsManager + + +@adapter_config(context=IViewsManager, provides=ISharedContentFactory) +def ViewsManagerContentFactory(context): + """Views manager content factory""" + return View @subscriber(IObjectAddedEvent, context_selector=IViewsManager)