use plone.base and remove dependencies to CMFPlone

This commit is contained in:
Jens W. Klein 2022-05-02 00:39:34 +02:00
parent 19571f45ed
commit f443deacbd
20 changed files with 153 additions and 102 deletions

View File

@ -11,12 +11,12 @@ from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.interfaces import IDiscussionSettings
from plone.app.discussion.interfaces import IReplies
from plone.app.layout.viewlets.common import ViewletBase
from plone.base.utils import safe_text
from plone.registry.interfaces import IRegistry
from plone.z3cform import z2
from plone.z3cform.fieldsets import extensible
from plone.z3cform.interfaces import IWrappedForm
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.utils import safe_unicode
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from Products.statusmessages.interfaces import IStatusMessage
from urllib.parse import quote
@ -151,9 +151,9 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
# Make sure author_name/ author_email is properly encoded
if "author_name" in data:
author_name = safe_unicode(data["author_name"])
author_name = safe_text(data["author_name"])
if "author_email" in data:
author_email = safe_unicode(data["author_email"])
author_email = safe_text(data["author_email"])
# Set comment author properties for anonymous users or members
portal_membership = getToolByName(context, "portal_membership")
@ -161,13 +161,13 @@ class CommentForm(extensible.ExtensibleForm, form.Form):
if not anon and getSecurityManager().checkPermission("Reply to item", context):
# Member
member = portal_membership.getAuthenticatedMember()
email = safe_unicode(member.getProperty("email"))
email = safe_text(member.getProperty("email"))
fullname = member.getProperty("fullname")
if not fullname or fullname == "":
fullname = member.getUserName()
fullname = safe_unicode(fullname)
fullname = safe_text(fullname)
author_name = fullname
email = safe_unicode(email)
email = safe_text(email)
# XXX: according to IComment interface author_email must not be # noqa T000
# set for logged in users, cite:
# 'for anonymous comments only, set to None for logged in comments'

View File

@ -48,7 +48,7 @@
<!-- Moderate comments enabled view -->
<browser:page
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
for="plone.base.interfaces.IPloneSiteRoot"
name="moderate-comments-enabled"
layer="..interfaces.IDiscussionLayer"
class=".moderation.ModerateCommentsEnabled"
@ -141,14 +141,14 @@
<!-- Control panel -->
<browser:page
name="discussion-controlpanel"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
for="plone.base.interfaces.IPloneSiteRoot"
class=".controlpanel.DiscussionSettingsControlPanel"
permission="cmf.ManagePortal"
/>
<!-- Deprecated controlpanel url -->
<browser:page
name="discussion-settings"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
for="plone.base.interfaces.IPloneSiteRoot"
class=".controlpanel.DiscussionSettingsControlPanel"
permission="cmf.ManagePortal"
/>

View File

@ -1,11 +1,12 @@
from plone.app.discussion.interfaces import _
from plone.app.discussion.interfaces import IDiscussionSettings
from plone.app.discussion.upgrades import update_registry
from ..interfaces import _
from ..interfaces import IDiscussionSettings
from ..upgrades import update_registry
from plone.app.registry.browser import controlpanel
from plone.base.interfaces.controlpanel import IConfigurationChangedEvent
from plone.base.interfaces.controlpanel import IMailSchema
from plone.registry.interfaces import IRecordModifiedEvent
from plone.registry.interfaces import IRegistry
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.interfaces.controlpanel import IMailSchema
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from Products.statusmessages.interfaces import IStatusMessage
from z3c.form import button
@ -16,16 +17,6 @@ from zope.component import queryUtility
from zope.component.hooks import getSite
# try/except was added because Configuration Changed Event was moved inside the
# controlpanel file in the PR #2495 on Products.CMFPlone
try:
from Products.CMFPlone.interfaces.controlpanel import ( # noqa: E501
IConfigurationChangedEvent,
)
except ImportError:
from Products.CMFPlone.interfaces import IConfigurationChangedEvent
class DiscussionSettingsEditForm(controlpanel.RegistryEditForm):
"""Discussion settings form."""

View File

@ -1,13 +1,13 @@
from ..interfaces import IDiscussionSettings
from Acquisition import aq_base
from Acquisition import aq_chain
from Acquisition import aq_inner
from plone.app.discussion.interfaces import IDiscussionSettings
from plone.base.interfaces import INonStructuralFolder
from plone.base.interfaces import IPloneSiteRoot
from plone.base.utils import safe_hasattr
from plone.registry.interfaces import IRegistry
from Products.CMFCore.interfaces import IFolderish
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.interfaces import INonStructuralFolder
from Products.CMFPlone.interfaces import IPloneSiteRoot
from Products.CMFPlone.utils import safe_hasattr
from zope.component import queryUtility

View File

@ -6,10 +6,10 @@ Also provide event handlers to actually catalog the comments.
from DateTime import DateTime
from plone.app.discussion.interfaces import IComment
from plone.app.discussion.interfaces import IConversation
from plone.base.utils import safe_text
from plone.indexer import indexer
from plone.uuid.interfaces import IUUID
from Products.CMFCore.interfaces import IContentish
from Products.CMFPlone.utils import safe_unicode
from Products.ZCatalog.interfaces import IZCatalog
@ -72,7 +72,7 @@ def title(object):
def creator(object):
if not object.creator:
return
value = safe_unicode(object.creator)
value = safe_text(object.creator)
return value

View File

@ -20,14 +20,14 @@ from plone.app.discussion.events import ReplyRemovedEvent
from plone.app.discussion.interfaces import IComment
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.interfaces import IDiscussionSettings
from plone.base.interfaces.controlpanel import IMailSchema
from plone.base.utils import safe_text
from plone.registry.interfaces import IRegistry
from Products.CMFCore import permissions
from Products.CMFCore.CMFCatalogAware import CatalogAware
from Products.CMFCore.CMFCatalogAware import WorkflowAware
from Products.CMFCore.DynamicType import DynamicType
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.interfaces.controlpanel import IMailSchema
from Products.CMFPlone.utils import safe_unicode
from smtplib import SMTPException
from zope.annotation.interfaces import IAnnotatable
from zope.component import getUtility
@ -205,8 +205,8 @@ class Comment(
Message(
COMMENT_TITLE,
mapping={
"author_name": safe_unicode(author_name),
"content": safe_unicode(content.Title()),
"author_name": safe_text(author_name),
"content": safe_text(content.Title()),
},
)
)
@ -374,7 +374,7 @@ def notify_user(obj, event):
Message(
MAIL_NOTIFICATION_MESSAGE,
mapping={
"title": safe_unicode(content_object.title),
"title": safe_text(content_object.title),
"link": content_object.absolute_url() + "/view#" + obj.id,
"text": obj.text,
},
@ -442,7 +442,7 @@ def notify_moderator(obj, event):
Message(
MAIL_NOTIFICATION_MESSAGE_MODERATOR,
mapping={
"title": safe_unicode(content_object.title),
"title": safe_text(content_object.title),
"link": content_object.absolute_url() + "/view#" + obj.id,
"text": obj.text,
"commentator": obj.author_email

View File

@ -39,7 +39,7 @@
description="Commenting infrastructure for Plone"
directory="profiles/default"
provides="Products.GenericSetup.interfaces.EXTENSION"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
for="plone.base.interfaces.IPloneSiteRoot"
/>
<!-- For upgrade steps see upgrades.zcml. -->

View File

@ -9,6 +9,10 @@ manipulate the same data structures, but provide an API for finding and
manipulating the comments directly in reply to a particular comment or at the
top level of the conversation.
"""
from .comment import Comment
from .interfaces import DISCUSSION_ANNOTATION_KEY as ANNOTATION_KEY
from .interfaces import IConversation
from .interfaces import IReplies
from AccessControl.SpecialUsers import nobody as user_nobody
from Acquisition import aq_base
from Acquisition import aq_inner
@ -21,11 +25,7 @@ from OFS.event import ObjectWillBeAddedEvent
from OFS.event import ObjectWillBeRemovedEvent
from OFS.Traversable import Traversable
from persistent import Persistent
from plone.app.discussion.comment import Comment
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.interfaces import IReplies
from Products.CMFPlone import DISCUSSION_ANNOTATION_KEY as ANNOTATION_KEY
from Products.CMFPlone.interfaces import IHideFromBreadcrumbs
from plone.base.interfaces import IHideFromBreadcrumbs
from zope.annotation.interfaces import IAnnotatable
from zope.annotation.interfaces import IAnnotations
from zope.component import adapter

View File

@ -11,6 +11,9 @@ from zope.interface.common.mapping import IIterableMapping
from zope.interface.interfaces import IObjectEvent
DISCUSSION_ANNOTATION_KEY = "plone.app.discussion:conversation"
def isEmail(value):
portal = getUtility(ISiteRoot)
reg_tool = getToolByName(portal, "portal_registration")

View File

@ -72,7 +72,7 @@
<!-- Control panel event subscribers -->
<subscriber
for="Products.CMFPlone.interfaces.events.IConfigurationChangedEvent"
for="plone.base.interfaces.events.IConfigurationChangedEvent"
handler=".browser.controlpanel.notify_configuration_changed"
/>

View File

@ -1,15 +1,13 @@
from .. import interfaces
from ..browser.comment import EditCommentForm
from ..browser.comments import CommentForm
from ..browser.comments import CommentsViewlet
from ..interfaces import IConversation
from ..interfaces import IDiscussionSettings
from ..testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING
from AccessControl import Unauthorized
from datetime import datetime
from OFS.Image import Image
from plone.app.discussion import interfaces
from plone.app.discussion.browser.comment import EditCommentForm
from plone.app.discussion.browser.comments import CommentForm
from plone.app.discussion.browser.comments import CommentsViewlet
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.interfaces import IDiscussionSettings
from plone.app.discussion.testing import ( # noqa
PLONE_APP_DISCUSSION_INTEGRATION_TESTING,
)
from plone.app.testing import login
from plone.app.testing import logout
from plone.app.testing import setRoles
@ -17,7 +15,6 @@ from plone.app.testing import TEST_USER_ID
from plone.app.testing import TEST_USER_NAME
from plone.registry.interfaces import IRegistry
from Products.CMFCore.utils import getToolByName
from Products.CMFPlone.tests import dummy
from z3c.form.interfaces import IFormLayer
from zope import interface
from zope.annotation.interfaces import IAttributeAnnotatable
@ -29,9 +26,43 @@ from zope.interface import alsoProvides
from zope.interface import Interface
from zope.publisher.browser import TestRequest
from zope.publisher.interfaces.browser import IBrowserRequest
from ZPublisher.HTTPRequest import FileUpload
import time
import unittest
import io
TEXT = b"file data"
class DummyFile(FileUpload):
"""Dummy upload object
Used to fake uploaded files.
"""
__allow_access_to_unprotected_subobjects__ = 1
filename = "dummy.txt"
data = TEXT
headers = {}
def __init__(self, filename=None, data=None, headers=None):
if filename is not None:
self.filename = filename
if data is not None:
self.data = data
if headers is not None:
self.headers = headers
self.file = io.BytesIO(self.data)
def seek(self, *args):
pass
def tell(self, *args):
return 1
def read(self, *args):
return self.data
class TestCommentForm(unittest.TestCase):
@ -631,7 +662,7 @@ class TestCommentsViewlet(unittest.TestCase):
self.memberdata._setPortrait(
Image(
id="jim",
file=dummy.File(),
file=DummyFile(),
title="",
),
"jim",

View File

@ -1,13 +1,13 @@
from ..interfaces import IComment
from ..interfaces import IConversation
from ..interfaces import IDiscussionLayer
from ..interfaces import IDiscussionSettings
from ..interfaces import IReplies
from ..testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING
from Acquisition import aq_base
from Acquisition import aq_parent
from datetime import datetime
from datetime import timedelta
from plone.app.discussion import interfaces
from plone.app.discussion.interfaces import IComment
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.interfaces import IDiscussionSettings
from plone.app.discussion.interfaces import IReplies
from plone.app.discussion.testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING
from plone.app.testing import setRoles
from plone.app.testing import TEST_USER_ID
from plone.app.vocabularies.types import BAD_TYPES
@ -29,7 +29,7 @@ class ConversationTest(unittest.TestCase):
def setUp(self):
self.portal = self.layer["portal"]
setRoles(self.portal, TEST_USER_ID, ["Manager"])
interface.alsoProvides(self.portal.REQUEST, interfaces.IDiscussionLayer)
interface.alsoProvides(self.portal.REQUEST, IDiscussionLayer)
self.typetool = self.portal.portal_types
self.portal_discussion = getToolByName(
@ -675,7 +675,7 @@ class ConversationEnabledForDexterityTypesTest(unittest.TestCase):
setRoles(self.portal, TEST_USER_ID, ["Manager"])
interface.alsoProvides(
self.portal.REQUEST,
interfaces.IDiscussionLayer,
IDiscussionLayer,
)
interface.alsoProvides(

View File

@ -1,8 +1,6 @@
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.interfaces import IReplies
from plone.app.discussion.testing import ( # noqa
PLONE_APP_DISCUSSION_INTEGRATION_TESTING,
)
from ..interfaces import IConversation
from ..interfaces import IReplies
from ..testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING
from plone.app.testing import setRoles
from plone.app.testing import TEST_USER_ID
from Zope2.App import zcml

View File

@ -2,7 +2,7 @@
These test are only triggered when Plone 4 (and plone.testing) is installed.
"""
from plone.app.discussion.testing import PLONE_APP_DISCUSSION_FUNCTIONAL_TESTING # noqa
from ..testing import PLONE_APP_DISCUSSION_FUNCTIONAL_TESTING # noqa
from plone.testing import layered
import doctest

View File

@ -1,12 +1,10 @@
"""Test for the plone.app.discussion indexers
"""
from .. import catalog
from ..interfaces import IConversation
from ..testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING # noqa
from datetime import datetime
from DateTime import DateTime
from plone.app.discussion import catalog
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.testing import ( # noqa
PLONE_APP_DISCUSSION_INTEGRATION_TESTING,
)
from plone.app.testing import setRoles
from plone.app.testing import TEST_USER_ID
from plone.indexer.delegate import DelegatingIndexerFactory

View File

@ -1,12 +1,10 @@
from plone.app.discussion.browser.moderation import BulkActionsView
from plone.app.discussion.browser.moderation import CommentTransition
from plone.app.discussion.browser.moderation import DeleteComment
from plone.app.discussion.browser.moderation import View
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.interfaces import IDiscussionSettings
from plone.app.discussion.testing import ( # noqa
PLONE_APP_DISCUSSION_INTEGRATION_TESTING,
)
from ..browser.moderation import BulkActionsView
from ..browser.moderation import CommentTransition
from ..browser.moderation import DeleteComment
from ..browser.moderation import View
from ..interfaces import IConversation
from ..interfaces import IDiscussionSettings
from ..testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING
from plone.app.testing import setRoles
from plone.app.testing import TEST_USER_ID
from plone.registry.interfaces import IRegistry

View File

@ -1,12 +1,10 @@
from plone.app.discussion.browser.moderation import BulkActionsView
from plone.app.discussion.browser.moderation import CommentTransition
from plone.app.discussion.browser.moderation import DeleteComment
from plone.app.discussion.browser.moderation import View
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.interfaces import IDiscussionSettings
from plone.app.discussion.testing import ( # noqa
PLONE_APP_DISCUSSION_INTEGRATION_TESTING,
)
from ..browser.moderation import BulkActionsView
from ..browser.moderation import CommentTransition
from ..browser.moderation import DeleteComment
from ..browser.moderation import View
from ..interfaces import IConversation
from ..interfaces import IDiscussionSettings
from ..testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING
from plone.app.testing import setRoles
from plone.app.testing import TEST_USER_ID
from plone.registry.interfaces import IRegistry

View File

@ -1,14 +1,14 @@
from ..interfaces import IConversation
from ..testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING
from Acquisition import aq_base
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.testing import ( # noqa
PLONE_APP_DISCUSSION_INTEGRATION_TESTING,
)
from persistent.list import PersistentList
from plone.app.testing import setRoles
from plone.app.testing import TEST_USER_ID
from plone.base.interfaces import IMailSchema
from plone.registry.interfaces import IRegistry
from Products.CMFPlone.interfaces import IMailSchema
from Products.CMFPlone.tests.utils import MockMailHost
from Products.MailHost.interfaces import IMailHost
from Products.MailHost.MailHost import _mungeHeaders
from Products.MailHost.MailHost import MailBase
from zope.component import createObject
from zope.component import getSiteManager
from zope.component import getUtility
@ -17,6 +17,42 @@ from zope.component import queryUtility
import unittest
class MockMailHost(MailBase):
"""A MailHost that collects messages instead of sending them."""
def __init__(self, id):
self.reset()
def reset(self):
self.messages = PersistentList()
def _send(self, mfrom, mto, messageText, immediate=False):
"""Send the message"""
self.messages.append(messageText)
def send(
self,
messageText,
mto=None,
mfrom=None,
subject=None,
encode=None,
immediate=False,
charset=None,
msg_type=None,
):
"""send *messageText* modified by the other parameters.
*messageText* can either be an ``email.message.Message``
or a string.
Note that Products.MailHost 4.10 had changes here.
"""
msg, mto, mfrom = _mungeHeaders(
messageText, mto, mfrom, subject, charset, msg_type, encode
)
self.messages.append(msg)
class TestUserNotificationUnit(unittest.TestCase):
layer = PLONE_APP_DISCUSSION_INTEGRATION_TESTING

View File

@ -1,4 +1,4 @@
from plone.app.discussion.testing import PLONE_APP_DISCUSSION_ROBOT_TESTING
from ..testing import PLONE_APP_DISCUSSION_ROBOT_TESTING
from plone.app.testing import ROBOT_TEST_LEVEL
from plone.testing import layered

View File

@ -1,11 +1,9 @@
"""Test plone.app.discussion workflow and permissions.
"""
from ..interfaces import IConversation
from ..interfaces import IDiscussionLayer
from ..testing import PLONE_APP_DISCUSSION_INTEGRATION_TESTING
from AccessControl import Unauthorized
from plone.app.discussion.interfaces import IConversation
from plone.app.discussion.interfaces import IDiscussionLayer
from plone.app.discussion.testing import ( # noqa
PLONE_APP_DISCUSSION_INTEGRATION_TESTING,
)
from plone.app.testing import login
from plone.app.testing import logout
from plone.app.testing import setRoles