--- 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
--- 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"""
--- 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"""
--- 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()
--- 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"""
--- 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
--- 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
#
--- 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)
--- 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 <tflorac AT ulthar.net>
-# 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
--- 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)
--- 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"""
--- 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)
--- 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)
--- 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"""
--- 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)
--- 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)
--- 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"""
--- 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)
--- 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
--- 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"""
--- 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"""
--- 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
--- 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
--- 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"""
--- 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"""
--- 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
--- 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']
--- 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):
--- 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)
--- 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"""
--- 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)