Skip to content

Commit

Permalink
Merge pull request #46 from collective/issue-42-blog-rename
Browse files Browse the repository at this point in the history
Rename Blog fti to BlogFolder
  • Loading branch information
sneridagh authored Nov 28, 2023
2 parents 68fa85d + d3d3743 commit fcabf61
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 10 deletions.
1 change: 1 addition & 0 deletions news/42.bug
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Rename Blog fti to BlogFolder, allowing contents with id blog to be added [@ericof]
2 changes: 1 addition & 1 deletion src/collective/blog/profiles/default/metadata.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<metadata>
<version>1001</version>
<version>1002</version>
<dependencies>
<!-- <dependency>profile-plone.volto:default</dependency> -->
</dependencies>
Expand Down
4 changes: 4 additions & 0 deletions src/collective/blog/profiles/default/types.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
/>
<object meta_type="Dexterity FTI"
name="Blog"
remove="True"
/>
<object meta_type="Dexterity FTI"
name="BlogFolder"
/>
<object meta_type="Dexterity FTI"
name="Post"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<object xmlns:i18n="http://xml.zope.org/namespaces/i18n"
meta_type="Dexterity FTI"
name="Blog"
name="BlogFolder"
i18n:domain="collective.blog"
>

<!-- Basic properties -->
<property name="title"
i18n:translate=""
>Blog</property>
>BlogFolder</property>
<property name="description"
i18n:translate=""
>A folderish content item representing a Blog</property>

<property name="allow_discussion">False</property>
<property name="factory">Blog</property>
<property name="factory">BlogFolder</property>
<property name="icon_expr" />
<property name="link_target" />

Expand Down Expand Up @@ -53,7 +53,7 @@
</property>

<!-- View information -->
<property name="add_view_expr">string:${folder_url}/++add++Blog</property>
<property name="add_view_expr">string:${folder_url}/++add++BlogFolder</property>
<property name="immediate_view">view</property>
<property name="default_view">view</property>
<property name="default_view_fallback">False</property>
Expand Down
15 changes: 15 additions & 0 deletions src/collective/blog/upgrades/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,20 @@
/>
</genericsetup:upgradeSteps>

<genericsetup:upgradeSteps
profile="collective.blog:default"
source="1001"
destination="1002"
>
<genericsetup:upgradeDepends
title="Rename Blog fti as BlogFolder"
import_steps="typeinfo"
/>
<genericsetup:upgradeStep
title="Update old Blog objects with new portal_type"
handler=".v1002.recatalog_portal_type"
/>
</genericsetup:upgradeSteps>


</configure>
33 changes: 33 additions & 0 deletions src/collective/blog/upgrades/v1002.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from collective.blog import logger
from plone import api
from Products.GenericSetup.tool import SetupTool


TYPES_MAPPING = (("Blog", "BlogFolder"),)


def _migrate_existing_content(old_pt: str, new_pt: str) -> int:
"""Update existing content items."""
with api.env.adopt_roles(["Manager"]):
# Search catalog as Manager
brains = api.content.find(portal_type=old_pt)
total = len(brains)
logger.info(f"Convert {total} {old_pt} instances to {new_pt}")
for brain in brains:
obj = brain.getObject()
obj.portal_type = new_pt
obj.reindexObject(
idxs=[
"portal_type",
"Type",
],
)
return total


def recatalog_portal_type(setup_tool: SetupTool):
"""Recatalog portal type for existing content items."""
for old_pt, new_pt in TYPES_MAPPING:
items = _migrate_existing_content(old_pt, new_pt)
logger.info(f"Converted {items} {old_pt} instances")
logger.info("Upgrade complete")
6 changes: 3 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ def all_content() -> list:
},
{
"_container": "/",
"type": "Blog",
"type": "BlogFolder",
"id": "tech-blog",
"title": "Awesome Tech Blog",
"description": "My awesome technical blog",
},
{
"_container": "/",
"type": "Blog",
"type": "BlogFolder",
"id": "dumpster",
"title": "General",
"description": "Posts about life, universe and everything",
Expand Down Expand Up @@ -106,7 +106,7 @@ def all_content() -> list:
@pytest.fixture
def blogs_payload(all_content, filter_items) -> list:
"""Payload to create two blogs items."""
return filter_items(all_content, "Blog", True)
return filter_items(all_content, "BlogFolder", True)


@pytest.fixture
Expand Down
21 changes: 20 additions & 1 deletion tests/content/test_blog.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from AccessControl.PermissionRole import rolesForPermissionOn
from collective.blog.content.blog import Blog
from copy import deepcopy
from plone import api
from plone.dexterity.content import DexterityContent
from plone.dexterity.fti import DexterityFTI
Expand All @@ -8,7 +9,7 @@
import pytest


CONTENT_TYPE = "Blog"
CONTENT_TYPE = "BlogFolder"


@pytest.fixture
Expand Down Expand Up @@ -75,6 +76,24 @@ def test_create(self, blogs_payload):
assert content.portal_type == CONTENT_TYPE
assert isinstance(content, Blog)

@pytest.mark.parametrize(
"content_id,expected",
[
("blog", "blog"),
("a-blog", "a-blog"),
("blog_name", "blog_name"),
("blog-folder", "blog-folder"),
("blog_folder", "blog_folder"),
("blogfolder", "blogfolder"),
],
)
def test_create_valid_ids(self, blogs_payload, content_id, expected):
payload = deepcopy(blogs_payload[0])
payload["id"] = content_id
with api.env.adopt_roles(["Manager"]):
content = api.content.create(container=self.portal, **payload)
assert content.id == expected

def test_blog_info_behavior_applied(self, blog):
from collective.blog.behaviors.blog import IBlogInfo

Expand Down
2 changes: 1 addition & 1 deletion tests/setup/test_setup_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ def test_browserlayer(self, browser_layers):

def test_latest_version(self, profile_last_version):
"""Test latest version of default profile."""
assert profile_last_version(f"{PACKAGE_NAME}:default") == "1001"
assert profile_last_version(f"{PACKAGE_NAME}:default") == "1002"
29 changes: 29 additions & 0 deletions tests/setup/upgrades/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from collective.blog import PACKAGE_NAME
from plone import api

import pytest


PROFILE_ID = f"profile-{PACKAGE_NAME}:default"


@pytest.fixture
def do_rollback(portal):
"""Rollback profile config."""

def func(src: str):
with api.env.adopt_roles(["Manager"]):
setup_tool = portal.portal_setup
setup_tool.setLastVersionForProfile(PROFILE_ID, src)

return func


@pytest.fixture
def do_upgrade(portal):
def func(dest: str):
with api.env.adopt_roles(["Manager"]):
setup_tool = portal.portal_setup
setup_tool.upgradeProfile(PROFILE_ID, dest=dest)

return func
69 changes: 69 additions & 0 deletions tests/setup/upgrades/test_upgrades_to_v1002.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from collective.blog.content.blog import Blog
from collective.blog.upgrades.v1002 import TYPES_MAPPING
from copy import deepcopy
from plone import api
from plone.dexterity.fti import DexterityFTI

import pytest


@pytest.fixture
def modify_ftis(portal, get_fti):
"""Modify fti"""

def func():
with api.env.adopt_roles(["Manager"]):
# Rename new content type back to its old name
types_tool = portal.portal_types
for old_pt, new_pt in TYPES_MAPPING:
types_tool.manage_renameObject(new_pt, old_pt)
fti = get_fti(old_pt)
fti.title = old_pt

return func


@pytest.fixture
def old_blog_factory(portal, blogs_payload):
def func() -> Blog:
with api.env.adopt_roles(["Manager"]):
payload = deepcopy(blogs_payload[0])
payload["type"] = "Blog"
payload["id"] = "old-blog"
return api.content.create(portal, **payload)

return func


class TestUpgradeV1002:
src: str = "1001"
dest: str = "1002"

@pytest.fixture(autouse=True)
def _init(self, get_fti, do_rollback, do_upgrade, modify_ftis, old_blog_factory):
do_rollback(self.src)
modify_ftis()
self.get_fti = get_fti
self.old_blog = old_blog_factory()
self.upgrade = do_upgrade

def test_blog_fti_available_in_1001(self):
assert isinstance(self.get_fti("Blog"), DexterityFTI)
assert self.get_fti("BlogFolder") is None

def test_blogfolder_fti_available_in_1002(self, do_upgrade):
do_upgrade(self.dest)
assert isinstance(self.get_fti("BlogFolder"), DexterityFTI)
assert self.get_fti("Blog") is None

def test_old_blogs_migrated(self, do_upgrade):
with api.env.adopt_roles(["Manager"]):
brains = api.content.find(portal_type="BlogFolder")
assert len(brains) == 0
# Upgrade
do_upgrade(self.dest)
with api.env.adopt_roles(["Manager"]):
brains = api.content.find(portal_type="BlogFolder")
assert len(brains) == 1
assert self.old_blog.portal_type == "BlogFolder"
assert self.old_blog.Type() == "BlogFolder"

0 comments on commit fcabf61

Please sign in to comment.