Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Changelog
3.0.0b1 (unreleased)
--------------------

- Nothing changed yet.
- Implement functionality to hide related resource from being displayed for
unpublished content


3.0.0b0 (2021-04-30)
Expand Down
10 changes: 10 additions & 0 deletions castle/cms/browser/viewlets/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@
layer="castle.cms.interfaces.ICastleLayer"
template="social_tags_body.pt"
/>

<browser:viewlet
name="plone.belowcontentbody.relateditems"
manager="plone.app.layout.viewlets.interfaces.IBelowContentBody"
for="plone.app.relationfield.behavior.IRelatedItems"
class="castle.cms.browser.viewlets.relateditems.ContentRelatedItems"
permission="zope2.View"
layer="castle.cms.interfaces.ICastleLayer"
/>

</configure>

</configure>
31 changes: 31 additions & 0 deletions castle/cms/browser/viewlets/relateditems.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from plone.app.layout.viewlets.content import ContentRelatedItems as BaseContentRelatedItems
from Products.CMFCore.utils import getToolByName
from plone import api


class ContentRelatedItems(BaseContentRelatedItems):

# override this method to respect castle.display_unpublished_related_items registry setting
def related2brains(self, related):
catalog = getToolByName(self.context, "portal_catalog")
brains = []
for r in related:
path = r.to_path
if path is None:
# Item was deleted. The related item should have been cleaned
# up, but apparently this does not happen.
continue
# the query will return an empty list if the user
# has no permission to see the target object
catalog_args = {
'path': dict(query=path, depth=0),
}
if not api.portal.get_registry_record(
'plone.display_unpublished_related_items',
default=False,
):
catalog_args['review_state'] = 'published'
brains.extend(
catalog(**catalog_args)
)
return brains
8 changes: 8 additions & 0 deletions castle/cms/interfaces/controlpanel.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,14 @@ class ISecuritySchema(controlpanel.ISecuritySchema):
default=False,
required=False)

display_unpublished_related_items = schema.Bool(
title=u'Display unpublished related items',
description=u'Check this box to allow Related Items that are not currently published '
u'to be displayed when viewing content containing related items.',
default=False,
required=False,
)


class IAnnouncementData(Interface):
show_announcement = schema.Bool(
Expand Down
4 changes: 4 additions & 0 deletions castle/cms/profiles/3_0_00/metadata.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0"?>
<metadata>
<version>3000</version>
</metadata>
12 changes: 12 additions & 0 deletions castle/cms/profiles/3_0_00/registry.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0"?>
<registry xmlns:i18n="http://xml.zope.org/namespaces/i18n"
i18n:domain="plone">

<record
name="plone.display_unpublished_related_items"
interface="castle.cms.interfaces.ISecuritySchema"
field="display_unpublished_related_items"
>
<value>False</value>
</record>
</registry>
2 changes: 1 addition & 1 deletion castle/cms/profiles/default/metadata.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<metadata>
<version>2631</version>
<version>3000</version>
<dependencies>
<dependency>profile-plone.app.querystring:default</dependency>
<dependency>profile-plone.app.mosaic:default</dependency>
Expand Down
106 changes: 106 additions & 0 deletions castle/cms/tests/test_related_resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# -*- coding: utf-8 -*-
import unittest

from castle.cms.testing import CASTLE_PLONE_INTEGRATION_TESTING
from plone import api
from plone.app.testing import TEST_USER_ID
from plone.app.testing import TEST_USER_NAME
from plone.app.testing import login
from plone.app.testing import setRoles
from zope.component import getUtility
from zope.intid.interfaces import IIntIds
from z3c.relationfield import RelationValue
from castle.cms.browser.viewlets.relateditems import ContentRelatedItems


class TestRelatedResources(unittest.TestCase):

layer = CASTLE_PLONE_INTEGRATION_TESTING

def setUp(self):
self.portal = self.layer['portal']
self.request = self.layer['request']
self.intid_utility = getUtility(IIntIds)

login(self.portal, TEST_USER_NAME)
setRoles(self.portal, TEST_USER_ID, ('Member', 'Manager'))
self.source_document = self.create_document('source')

def create_document(self, id):
return api.content.create(
type='Document',
id=id,
container=self.portal,
)

def publish(self, item):
api.content.transition(
obj=item,
to_state='published',
)

@property
def related_items(self):
content_related_items = ContentRelatedItems(
context=self.source_document,
request=self.source_document.REQUEST,
view=self.source_document.view,
)
return [
brain.getObject()
for brain in content_related_items.related_items()
]

def set_up_target_documents(self):
target_documents = [
self.create_document('target_1'),
self.create_document('target_2'),
]
self.source_document.relatedItems = [
RelationValue(self.intid_utility.getId(target))
for target in target_documents
]
self.assertEqual(
len(self.source_document.relatedItems),
2,
)
return target_documents

def assertContentRelatedItemsLength(self, asserted_length):
self.assertEqual(
len(self.related_items),
asserted_length,
)

def test_display_unpublished_related_items_false_by_default(self):
display_unpublished_related_items = api.portal.get_registry_record(
'plone.display_unpublished_related_items',
default=True,
)
self.assertFalse(display_unpublished_related_items)

def test_content_related_items_override_when_display_unpublished_false(self):
target_documents = self.set_up_target_documents()
api.portal.set_registry_record(
'plone.display_unpublished_related_items',
False,
)
self.assertEqual(len(self.related_items), 0)
for expected_related_items_count, target_document in enumerate(target_documents, start=1):
self.assertFalse(target_document in self.related_items)
self.publish(target_document)
self.assertEqual(
len(self.related_items),
expected_related_items_count,
)
self.assertTrue(target_document in self.related_items)

def test_content_related_items_override_when_display_unpublished_true(self):
target_documents = self.set_up_target_documents()
api.portal.set_registry_record(
'plone.display_unpublished_related_items',
True,
)
self.assertEqual(len(self.related_items), 2)
for target_document in target_documents:
self.assertTrue(target_document in self.related_items)
22 changes: 20 additions & 2 deletions castle/cms/upgrades.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@

<genericsetup:upgradeStep
title="Upgrade CastleCMS to 2.6.30"
description="changes default slideshow view to the actual slideshow"
description="2630 changes default slideshow view to the actual slideshow"
source="*"
destination="2630"
handler=".upgrades.upgrade_2_6_30"
Expand All @@ -458,10 +458,28 @@

<genericsetup:upgradeStep
title="Upgrade CastleCMS to 2.6.31"
description="adds/ fixes some mockup-structure pagination functionality"
description="2631 adds/ fixes some mockup-structure pagination functionality"
source="*"
destination="2631"
handler=".upgrades.upgrade_2_6_31"
profile="castle.cms:default"
/>

<genericsetup:registerProfile
name="3_0_00"
title="CastleCMS upgrade to 3.0.0 profile"
directory="profiles/3_0_00"
description=""
provides="Products.GenericSetup.interfaces.EXTENSION"
/>

<genericsetup:upgradeStep
title="Upgrade CastleCMS to 3.0.0"
description="3000 adds the functionality to filter out unpublished related items"
source="*"
destination="3000"
handler=".upgrades.upgrade_3_0_00"
profile="castle.cms:default"
/>

</configure>
2 changes: 2 additions & 0 deletions castle/cms/upgrades/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,5 @@ def upgrade(context, logger=None):
upgrade_2_6_27 = default_upgrade_factory('2_6_27')
upgrade_2_6_30 = default_upgrade_factory('2_6_30')
upgrade_2_6_31 = default_upgrade_factory('2_6_31')

upgrade_3_0_00 = default_upgrade_factory('3_0_00')
11 changes: 10 additions & 1 deletion docs/controlpanel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,13 @@ The can be configured on the environment with these environment settings:
- `GOOGLE_CLIENT_SECRET`

(you can also provide twitter auth key and secret through control panel; however,
in the future, these will all be environment variables)
in the future, these will all be environment variables)


Security Settings
-----------------

in /@@security-controlpanel, you can change settings for the way some content shows
up. For example, `Allow access to published objects inside private containers` and
`Display unpublished related items` settings can be changed there. (Both of these
values default to False)