Commit 6bf9e694 authored by Julien Muchembled's avatar Julien Muchembled

Merge support for ZODB indexing of category related documents

parents a7780bc6 7865c58d
No related merge requests found
This diff is collapsed.
......@@ -544,7 +544,8 @@ class BaseTemplateItem(Implicit, Persistent):
klass = obj.__class__
classname = klass.__name__
attr_set = set(('_dav_writelocks', '_filepath', '_owner', 'last_id', 'uid',
attr_set = set(('_dav_writelocks', '_filepath', '_owner', '_related_index',
'last_id', 'uid',
'__ac_local_roles__', '__ac_local_roles_group_id_dict__'))
if export:
if not keep_workflow_history:
......
......@@ -40,6 +40,7 @@ from Products.ERP5Type.Core.Folder import OFS_HANDLER
from Products.ERP5Type.CopySupport import CopyContainer
from Products.CMFCore.utils import getToolByName
from Products.ERP5Type.Cache import caching_instance_method
from Products.ERP5Type.dynamic import portal_type_class
from zLOG import LOG
......@@ -84,54 +85,10 @@ class CategoryTool(CopyContainer, CMFCategoryTool, BaseTool):
def hasContent(self,id):
return id in self.objectIds()
security.declareProtected(Permissions.AccessContentsInformation, 'getCategoryParentUidList')
def getCategoryParentUidList(self, relative_url, base_category = None, strict=0):
"""
Returns the uids of all categories provided in categorie. This
method can support relative_url such as site/group/a/b/c which
base category is site yet use categories defined in group.
It is also able to use acquisition to create complex categories
such as site/group/a/b/c/b1/c1 where b and b1 are both children
categories of a.
relative_url -- a single relative url of a list of
relative urls
strict -- if set to 1, only return uids of parents, not
relative_url
"""
uid_dict = {}
if type(relative_url) is type('a'): relative_url = (relative_url,)
for path in relative_url:
try:
o = self.getCategoryValue(path, base_category=base_category)
if o is not None:
if base_category is None:
my_base_category = self.getBaseCategoryId(path)
else:
my_base_category = base_category
bo = getattr(self, my_base_category, None)
if bo is not None:
bo_uid = bo.getUid()
uid_dict[(o.getUid(), bo_uid, 1)] = 1 # Strict membership
if o.meta_type == 'ERP5 Category' or o.meta_type == 'ERP5 Base Category' or \
o.meta_type == 'CMF Category' or o.meta_type == 'CMF Base Category':
# This goes up in the category tree
# XXX we should also go up in some other cases....
# ie. when some documents act as categories
if not strict:
while o.meta_type == 'ERP5 Category' or o.meta_type == 'CMF Category':
o = o.aq_parent # We want acquisition here without aq_inner
uid_dict[(o.getUid(), bo_uid, 0)] = 1 # Non strict
except (TypeError, KeyError):
LOG('WARNING: CategoriesTool',0, 'Unable to find uid for %s' % path)
return uid_dict.keys()
security.declareProtected(Permissions.AccessContentsInformation, 'getUids')
getUids = getCategoryParentUidList
@caching_instance_method(id='portal_categories.getBaseCategoryDict', cache_factory='erp5_content_long', cache_id_generator=lambda m, *a, **k:m)
@caching_instance_method(
id='portal_categories.getBaseCategoryDict',
cache_factory='erp5_content_long',
cache_id_generator=lambda *a: portal_type_class.last_sync)
def getBaseCategoryDict(self):
"""
Cached method to which resturns a dict with category names as keys, and None as values.
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>return not (value and (\n
request.other[\'field_my_acquisition_object_id_list\'] or\n
request.other[\'field_my_acquisition_base_category_list\']))\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>value, request</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>BaseCategory_validateRelatedLocallyIndexed</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -105,6 +105,7 @@
<key> <string>right</string> </key>
<value>
<list>
<string>my_related_locally_indexed</string>
<string>my_acquisition_copy_value</string>
<string>my_acquisition_mask_value</string>
<string>my_acquisition_append_value</string>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>external_validator</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>delegated_message_list</string> </key>
<value>
<list>
<string>external_validator_failed</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_related_locally_indexed</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>Local index is incompatible with category acquision.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_checkbox</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Index Related Documents Locally</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Method" module="Products.Formulator.MethodField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>method_name</string> </key>
<value> <string>BaseCategory_validateRelatedLocallyIndexed</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
......@@ -58,15 +58,11 @@ order_by_expression</string> </value>
<key> <string>src</string> </key>
<value> <string encoding="cdata"><![CDATA[
SELECT DISTINCT catalog.uid, catalog.path, portal_type\n
SELECT DISTINCT catalog.uid, path, relative_url, portal_type\n
FROM catalog, category\n
WHERE catalog.uid = category.uid\n
<dtml-if portal_type>\n
AND\n
(<dtml-in portal_type>\n
<dtml-unless sequence-start> OR </dtml-unless>\n
catalog.portal_type=\'<dtml-var sequence-item>\'\n
</dtml-in>)\n
AND <dtml-sqltest portal_type type="string" multiple>\n
</dtml-if>\n
AND (<dtml-var "portal_categories.buildSQLSelector(category_list)">)\n
<dtml-if strict_membership>\n
......
41060
\ No newline at end of file
41061
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/boolean</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Determines if related values should be indexed on target documents (i.e. in ZODB) in addition to catalog.\n
This is incompatible with category acquisition.</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>related_locally_indexed_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
<item>
<key> <string>property_default</string> </key>
<value> <string>python: 0</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
56
\ No newline at end of file
57
\ No newline at end of file
......@@ -862,20 +862,19 @@ class TestResource(ERP5TypeTestCase):
self.tic()
# Test the cases
for product, variation, node, base_price in test_case_list:
categories = []
if node is not None:
self.logMessage("Check product %s with destination section %s" % \
(product.getTitle(), node.getTitle()),
tab=1)
self.assertEquals(base_price,
product.getPrice(
categories=['destination_section/%s' % node.getRelativeUrl(),
variation]))
categories.append('destination_section/' + node.getRelativeUrl())
else:
self.logMessage("Check product %s without destination section" % \
product.getTitle(),
tab=1)
self.assertEquals(base_price,
product.getPrice(categories=[variation]))
if variation:
categories.append(variation)
self.assertEqual(base_price, product.getPrice(categories=categories))
# The following test tests Movement.getPrice, which is based on the movement
......
......@@ -48,8 +48,7 @@ class SetSetter(BaseSetter):
def __call__(self, instance, *args, **kw):
if self._warning:
LOG("ERP5Type Deprecated Setter Id:",0, self._id)
value = set(args[0])
instance._setValue(self._key, value,
instance._setValue(self._key, set(args[0]),
spec=kw.get('spec',()),
filter=kw.get('filter', None),
portal_type=kw.get('portal_type',()),
......@@ -451,7 +450,7 @@ class UidSetSetter(BaseSetter):
def __call__(self, instance, *args, **kw):
if self._warning:
LOG("ERP5Type Deprecated Getter Id:",0, self._id)
instance._setValueUidList(self._key, args[0],
instance._setValueUidList(self._key, set(args[0]),
spec=kw.get('spec',()),
filter=kw.get('filter', None),
portal_type=kw.get('portal_type',()),
......
......@@ -2013,11 +2013,8 @@ class Base( CopyContainer,
checked_permission=None):
# We must do an ordered list so we can not use the previous method
# self._setValue(id, self.portal_catalog.getObjectList(uids), spec=spec)
references = []
if type(uids) not in (type(()), type([])):
uids = [uids]
for uid in uids:
references.append(self.portal_catalog.getObject(uid))
references = map(self.getPortalObject().portal_catalog.getObject,
(uids,) if isinstance(uids, (int, long)) else uids)
self._setValue(id, references, spec=spec, filter=filter, portal_type=portal_type,
keep_default=keep_default, checked_permission=checked_permission)
......@@ -2178,9 +2175,6 @@ class Base( CopyContainer,
"""
return self._getCategoryTool().getAcquiredCategoryList(self)
def _getAcquiredCategoryList(self):
return self._getCategoryTool()._getAcquiredCategoryList(self)
security.declareProtected( Permissions.ModifyPortalContent, 'setCategoryList' )
def setCategoryList(self, path_list):
self.portal_categories.setCategoryList(self, path_list)
......
......@@ -722,27 +722,21 @@ class TestERP5Type(PropertySheetTestCase, LogInterceptor):
self.assertEquals(person.getDefaultRegion(), 'alpha')
person.setRegionUid(alpha.getUid())
self.assertEquals(person.getRegion(), 'alpha')
person.setRegionUidList([alpha.getUid(), alpha.getUid()])
self.assertEquals(person.getRegionList(), ['alpha', 'alpha'])
person.setRegionUidList([beta.getUid(), beta.getUid()])
self.assertEquals(person.getRegionList(), ['beta', 'beta'])
person.setRegionUidSet([alpha.getUid(), alpha.getUid()])
self.assertEquals(person.getRegionSet(), ['alpha'])
self.assertEquals(person.getRegionList(), ['alpha'])
person.setRegionUidList([alpha.getUid(), beta.getUid(), alpha.getUid()])
self.assertEquals(person.getRegionList(), ['alpha', 'beta', 'alpha'])
person.setRegionUidSet([alpha.getUid(), beta.getUid(), alpha.getUid()])
result = person.getRegionSet()
result.sort()
self.assertEquals(result, ['alpha', 'beta'])
self.assertEquals(sorted(person.getRegionSet()), ['alpha', 'beta'])
person.setDefaultRegionUid(beta.getUid())
self.assertEquals(person.getDefaultRegion(), 'beta')
result = person.getRegionSet()
result.sort()
self.assertEquals(result, ['alpha', 'beta'])
self.assertEquals(sorted(person.getRegionSet()), ['alpha', 'beta'])
self.assertEquals(person.getRegionList(), ['beta', 'alpha'])
person.setDefaultRegionUid(alpha.getUid())
self.assertEquals(person.getDefaultRegion(), 'alpha')
result = person.getRegionSet()
result.sort()
self.assertEquals(result, ['alpha', 'beta'])
self.assertEquals(sorted(person.getRegionSet()), ['alpha', 'beta'])
self.assertEquals(person.getRegionList(), ['alpha', 'beta'])
# Test accessor on documents rather than on categories
person.setDefaultRegionUid(person.getUid())
......
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