Skip to content

Commit

Permalink
6.1: Cleanup plone.app.discussion settings when the package is not av…
Browse files Browse the repository at this point in the history
…ailable.

If the site contains comments, we throw an error and stop the upgrade.
The advice then is to add the `plone.app.discussion` package.
  • Loading branch information
mauritsvanrees committed Aug 13, 2024
1 parent f49c8c8 commit 100cf0e
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 2 deletions.
4 changes: 4 additions & 0 deletions news/211.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
6.1: Cleanup ``plone.app.discussion`` settings when the package is not available.
If the site contains comments, we throw an error and stop the upgrade.
The advice then is to add the ``plone.app.discussion`` package.
[maurits]
4 changes: 2 additions & 2 deletions plone/app/upgrade/v61/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@
>
<!-- Plone 6.1.0a5 -->
<gs:upgradeStep
title="Miscellaneous"
handler="..utils.null_upgrade_step"
title="Maybe get rid of plone.app.discussion"
handler=".final.maybe_cleanup_discussion"
/>
</gs:upgradeSteps>

Expand Down
82 changes: 82 additions & 0 deletions plone/app/upgrade/v61/final.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
from plone.registry.interfaces import IRegistry
from zope.component import getUtility
from Acquisition import aq_parent
from importlib.metadata import distribution
from importlib.metadata import PackageNotFoundError
from plone.app.upgrade.utils import loadMigrationProfile
from plone.browserlayer.utils import unregister_layer
from Products.CMFCore.utils import getToolByName
from zope.component import getSiteManager

import logging

Expand All @@ -21,3 +29,77 @@ def remove_portal_properties_tool(context):
# AttributeError: 'PropertiesTool' object has no attribute '__of__'
portal._delOb("portal_properties")
logger.info("Removed portal_properties tool.")


def maybe_cleanup_discussion(context):
"""Cleanup some left-overs from plone.app.discussion.
But only do this when the package is not available.
In Plone 6.1, the package was made into a core add-on.
Meaning: it no longer gets pulled in by Products.CMFPlone,
but only by the Plone package.
"""
# First check if the GS profile was installed.
profile_id = "plone.app.discussion:default"
if context.getLastVersionForProfile(profile_id) == "unknown":
logger.info("%s was not installed, nothing to do.", profile_id)
return
try:
distribution("plone.app.discussion")
logger.info("The plone.app.discussion package is available, so we do nothing.")
return
except PackageNotFoundError:
logger.info("plone.app.discussion package not found, will cleanup.")

# First check if there are any actual discussion items in the site.
catalog = getToolByName(context, "portal_catalog")
brains = catalog.unrestrictedSearchResults(portal_type="Discussion Item")
total = len(brains)
if total:
raise ValueError(
f"{total} Discussion Items (comments) were found in the site, but "
"plone.app.discussion is missing.\nThis package is optional since "
"Plone 6.1.\nPlease add plone.app.discussion to your Plone installation "
"if you want to keep using them."
)

# First apply a profile. This is mostly a copy of the uninstall profile
# of plone.app.discussion.
loadMigrationProfile(context, "profile-plone.app.upgrade.v61:uninstall-discussion")

# The registry keys were registered via the IDiscussionSettings interface
# which no longer exists, so we remove them one by one.
registry = getUtility(IRegistry)
records = registry.records
to_remove = [
key
for key in records.keys()
if "plone.app.discussion.interfaces.IDiscussionSettings" in key
]
for key in to_remove:
del records[key]
logger.info("Removed all IDiscussionSettings registry records.")

# Gather the FTIs that have the plone.allowdiscussion behavior.
# It can appear with the name or the interface identifier.
portal_types = getToolByName(context, "portal_types")
old_behaviors = {
"plone.allowdiscussion",
"plone.app.dexterity.behaviors.discussion.IAllowDiscussion",
}
ftis_to_fix = (
fti
for fti in portal_types.objectValues("Dexterity FTI")
if set(fti.behaviors) & old_behaviors
)
for fti in ftis_to_fix:
# Remove the behavior. Remember this is a tuple.
behaviors = [
behavior for behavior in fti.behaviors if behavior not in old_behaviors
]
# Set the updated behaviors
fti.behaviors = tuple(behaviors)
logger.info("Removed plone.allowdiscussion behavior from %s", fti)

# Mark GS profile as not installed/activated.
context.unsetLastVersionForProfile(profile_id)
9 changes: 9 additions & 0 deletions plone/app/upgrade/v61/profiles.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,13 @@
provides="Products.GenericSetup.interfaces.EXTENSION"
/>

<!-- This is a copy of plone.app.discussion/profiles/uninstall. -->
<genericsetup:registerProfile
name="uninstall-discussion"
title="Uninstall plone.app.discussion"
directory="profiles/uninstall-discussion"
for="plone.base.interfaces.IMigratingPloneSiteRoot"
provides="Products.GenericSetup.interfaces.EXTENSION"
/>

</configure>
13 changes: 13 additions & 0 deletions plone/app/upgrade/v61/profiles/uninstall-discussion/actions.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<object xmlns:i18n="http://xml.zope.org/namespaces/i18n"
name="portal_actions"
>
<object meta_type="CMF Action Category"
name="user"
>
<object meta_type="CMF Action"
name="review-comments"
remove="true"
/>
</object>
</object>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<layers>
<layer name="plone.app.discussion"
remove="true"
/>
</layers>
28 changes: 28 additions & 0 deletions plone/app/upgrade/v61/profiles/uninstall-discussion/catalog.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<object name="portal_catalog">

<index meta_type="FieldIndex"
name="total_comments"
remove="true"
/>
<index meta_type="KeywordIndex"
name="commentators"
remove="true"
/>
<column remove="true"
value="total_comments"
/>
<column remove="true"
value="last_comment_date"
/>
<column remove="true"
value="commentators"
/>
<column remove="true"
value="in_response_to"
/>
<column remove="true"
value="author_name"
/>

</object>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<object xmlns:i18n="http://xml.zope.org/namespaces/i18n"
name="portal_controlpanel"
purge="False"
i18n:domain="plone"
>

<configlet action_id="discussion"
appId="plone.app.discussion"
category="plone-content"
remove="true"
/>

</object>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<registry>
<!-- This would give ModuleNotFoundError: No module named 'plone.app.discussion'
So we do this in Python code in maybe_cleanup_discussion. -->
<!-- <records interface="plone.app.discussion.interfaces.IDiscussionSettings"
remove="true"
/> -->
</registry>
9 changes: 9 additions & 0 deletions plone/app/upgrade/v61/profiles/uninstall-discussion/types.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<object meta_type="CMF Types Tool"
name="portal_types"
>
<object meta_type="Factory-based Type Information"
name="Discussion Item"
remove="True"
/>
</object>
13 changes: 13 additions & 0 deletions plone/app/upgrade/v61/profiles/uninstall-discussion/workflows.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<object meta_type="Plone Workflow Tool"
name="portal_workflow"
>
<object meta_type="Workflow"
name="comment_review_workflow"
remove="True"
/>
<object meta_type="Workflow"
name="comment_one_state_workflow"
remove="True"
/>
</object>

0 comments on commit 100cf0e

Please sign in to comment.