-
Notifications
You must be signed in to change notification settings - Fork 20
Description
Modern versions (e.g. 2.5.4) of Products.CMFCore (more precisely its CMFCatalogAware.CatalogAware._getCatalogTool) no longer access the catalog via name but instead via utility lookup. This make problems for renaming (or moving in general) a portal.
If the renaming is called for outside a (site) context with a catalog, the portal's catalog is not updated (and continues to use the old paths). If the operation is called for in a site context with a catalog, then this catalog is updated -- however, this may be the wrong catalog.
The latter problem is demonstrated by the following console output. It sets up two portals p1 and p2 and then renames p1 in the p2 site context. At the end we see that p2.portal_catalog has wrongly received entries for the renamed p1 content.
>>> from transaction import savepoint
>>> from zope.component import getSiteManager
>>> from zope.component.hooks import setSite
>>> from zope.interface import implementer
>>> from OFS.Folder import Folder
>>>
>>> from Products.CMFCore.interfaces import IContentish
>>> from Products.CMFCore.PortalObject import PortalObjectBase
>>> from Products.CMFCore.CatalogTool import CatalogTool, ICatalogTool, processQueue
>>> from Products.CMFCore.PortalFolder import PortalFolder
>>> from Products.CMFCore.CMFCatalogAware import CatalogAware
>>> from Products.CMFCore.utils import getToolByName
>>>
>>> @implementer(IContentish)
... class PortalFolder(PortalFolder, CatalogAware): pass
...
>>> def setup_portal(pid):
... """set up a portal inside a folder; return portal."""
... f = Folder(pid + "_folder")
... app._setObject(f.getId(), f)
... f = app[f.getId()]
... po = PortalObjectBase(pid)
... f._setObject(po.getId(), po)
... po = f[po.getId()]
... setSite(po)
... catalog = CatalogTool()
... po._setObject(catalog.getId(), catalog)
... sm = getSiteManager()
... sm.registerUtility(po.portal_catalog, ICatalogTool)
... f = PortalFolder("test folder")
... po._setObject(f.getId(), f)
... f = po[f.getId()]
... f.indexObject()
... return po
...
>>> p1 = setup_portal("p1")
>>> processQueue()
1
>>> list(p1.portal_catalog._catalog.uids.items())
[('/p1_folder/p1/test folder', -1146243941)]
>>> p2 = setup_portal("p2")
>>> processQueue()
1
>>> list(p2.portal_catalog._catalog.uids.items())
[('/p2_folder/p2/test folder', 1954711366)]
>>> sp = savepoint()
>>> app.manage_renameObject("p1_folder", "p1_folder_renamed")
ERROR:Zope.ZCatalog:uncatalogObject unsuccessfully attempted to uncatalog an object with a uid of /p1_folder/p1/test folder.
>>> processQueue()
0
>>> list(p2.portal_catalog._catalog.uids.items())
[('/p1_folder_renamed/p1/test folder', 1954711367), ('/p2_folder/p2/test folder', 1954711366)]