Commit 5c4c69a0 authored by Vincent Pelletier's avatar Vincent Pelletier

Base: Add isSubtreeIndexable and isAncestryIndexable

isAncestryIndexable is a parent-recursive version of isIndexable: it
will return False if any parent is non-indeable. This simplifies
disabling indexation of an entire tree, from its root to its deepest
leaves.
isSubtreeIndexable allows preventing any subobject from being indexable,
without having to mark each individual subobject as non-indexable. This
is different from isAncestryIndexable, as it allows having an indexable
root, but no children indexable. This is especially useful for Trash Bins,
where the bin itself should be indexable (because there is no reason not to)
but its content must not be indexed, while being left as it was found in its
original location.
parent babbf56f
##############################################################################
#
# Copyright (c) 2018 Nexedi SARL and Contributors. All Rights Reserved.
# Vincent Pelletier <vincent@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
from AccessControl import ClassSecurityInfo
from Products.ERP5Type.Core.Folder import Folder
class TrashBin(Folder):
# meta_type = BBB: inherit
portal_type = 'Trash Bin'
security = ClassSecurityInfo()
security.declarePublic('isSubtreeIndexable')
def isSubtreeIndexable(self):
"""
Nothing is indexable inside a trash bin.
"""
return False
......@@ -266,6 +266,17 @@ class ERP5Site(FolderMixIn, CMFSite, CacheCookieMixin):
security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation)
security.declarePublic('isSubtreeIndexable')
def isSubtreeIndexable(self):
"""
Allow a container to preempt indexability of its content, without having
to set "isIndexable = False" on (at minimum) its immediate children.
The meaning of calling this method on an instance where
isAncestryIndexable returns False is undefined.
"""
return self.isIndexable
def __before_publishing_traverse__(self, self2, request):
request.RESPONSE.realm = None
return super(ERP5Site, self).__before_publishing_traverse__(self2, request)
......
......@@ -54,7 +54,7 @@
</item>
<item>
<key> <string>type_class</string> </key>
<value> <string>Folder</string> </value>
<value> <string>TrashBin</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -110,14 +110,6 @@ class TestVanillaERP5Catalog(ERP5TypeTestCase, LogInterceptor):
self.assertTrue(path not in path_list)
LOG('checkRelativeUrlInSQLPathList not found path:',0,path)
# This test fails because initial business template installation indexes
# installed objects using rules inconsistent with ERP5Site_reindexAll.
# This is not a regression: previously tests did not notice because they were
# not testing result set equality, but post-reindex being a superset of
# pre-reindex (bad), and pre-reindex was necessarily a subset because other
# tests run before were clearing catalog, making this test an exercise in
# futiliy.
@unittest.expectedFailure
def test_1_ERP5Site_reindexAll(self):
portal = self.getPortal()
portal.portal_categories.newContent(portal_type='Base Category', title="GreatTitle1")
......
......@@ -2788,9 +2788,36 @@ class Base( CopyContainer,
# def contentIds(self, *args, **kw):
# return []
security.declarePrivate('isSubtreeIndexable')
def isSubtreeIndexable(self):
"""
Allow a container to preempt indexability of its content, without having
to set "isIndexable = False" on (at minimum) its immediate children.
The meaning of calling this method on an instance where
isAncestryIndexable returns False is undefined.
"""
return self.isIndexable
security.declarePrivate('isAncestryIndexable')
def isAncestryIndexable(self):
"""
Tells whether this document is indexable, taking into account its entire
ancestry: a document may only be indexed if its parent is indexable, and
it's parent's parent, etc until ERP5Site object (inclusive).
"""
node = self.aq_inner
portal = aq_base(self.getPortalObject())
while True:
is_indexable = node.isSubtreeIndexable()
if not is_indexable or aq_base(node) is portal:
break
node = node.aq_parent
return is_indexable
security.declarePrivate('immediateReindexObject')
def immediateReindexObject(self, *args, **kw):
if self.isIndexable and int(getattr(self.getPortalObject(), 'isIndexable', 1)):
if self.isAncestryIndexable():
with super_user():
PortalContent.reindexObject(self, *args, **kw)
......@@ -2810,7 +2837,7 @@ class Base( CopyContainer,
# immediateReindexObject.
# Do not check if root is indexable, it is done into catalogObjectList,
# so we will save time
if self.isIndexable:
if self.isAncestryIndexable():
kw, activate_kw = self._getReindexAndActivateParameterDict(
kw,
activate_kw,
......@@ -2858,7 +2885,7 @@ class Base( CopyContainer,
"""
Get indexable childen recursively.
"""
if self.isIndexable:
if self.isAncestryIndexable():
return [self]
return []
......
......@@ -545,7 +545,6 @@ class CopyContainer:
def _setNonIndexable(self):
self.isIndexable = ConstantGetter('isIndexable', value=False)
self.__recurse('_setNonIndexable')
def manage_pasteObjects(self, cb_copy_data=None, is_indexable=None, reindex_kw=None, immediate_reindex=False, REQUEST=None):
"""Paste previously copied objects into the current object.
......
......@@ -1229,7 +1229,7 @@ class Folder(CopyContainer, OFSFolder2, CMFBTreeFolder, CMFHBTreeFolder, Base, F
security.declarePublic('recursiveReindexObject')
def recursiveReindexObject(self, activate_kw=None, **kw):
if self.isIndexable:
if self.isAncestryIndexable():
kw, activate_kw = self._getReindexAndActivateParameterDict(
kw,
activate_kw,
......@@ -1245,7 +1245,7 @@ class Folder(CopyContainer, OFSFolder2, CMFBTreeFolder, CMFHBTreeFolder, Base, F
)
def _isDocumentNonIndexable(self, document):
return not document.isIndexable
return not document.isSubtreeIndexable()
def _updateActivateKwWithSerialisationTag(self, document, activate_kw):
activate_kw['serialization_tag'] = document.getRootDocumentPath()
......@@ -1258,11 +1258,12 @@ class Folder(CopyContainer, OFSFolder2, CMFBTreeFolder, CMFHBTreeFolder, Base, F
Get indexable childen recursively.
"""
value_list = []
if self.isIndexable:
if self.isAncestryIndexable():
value_list.append(self)
for c in self.objectValues():
if getattr(aq_base(c), 'getIndexableChildValueList', None) is not None:
value_list.extend(c.getIndexableChildValueList())
if self.isSubtreeIndexable():
for c in self.objectValues():
if getattr(aq_base(c), 'getIndexableChildValueList', None) is not None:
value_list.extend(c.getIndexableChildValueList())
return value_list
security.declarePrivate('recursiveImmediateReindexObject')
......@@ -1303,7 +1304,7 @@ class Folder(CopyContainer, OFSFolder2, CMFBTreeFolder, CMFHBTreeFolder, Base, F
Called when the base of a hierarchy is renamed
"""
# Reindex self
if self.isIndexable:
if self.isAncestryIndexable():
self.moveObject()
# Reindex contents
for c in self.objectValues():
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment