Commit babf7a22 authored by Kazuhiko Shiozaki's avatar Kazuhiko Shiozaki

fixup! erp5_web: introduce translatable path.

parent 9d839e52
...@@ -41,6 +41,7 @@ from OFS.Traversable import NotFound ...@@ -41,6 +41,7 @@ from OFS.Traversable import NotFound
from OFS.ObjectManager import checkValidId from OFS.ObjectManager import checkValidId
from ZPublisher import BeforeTraverse from ZPublisher import BeforeTraverse
from Products.CMFCore.utils import _checkConditionalGET, _setCacheHeaders, _ViewEmulator from Products.CMFCore.utils import _checkConditionalGET, _setCacheHeaders, _ViewEmulator
from zExceptions import BadRequest
from Products.ERP5Type.Cache import getReadOnlyTransactionCache from Products.ERP5Type.Cache import getReadOnlyTransactionCache
...@@ -113,11 +114,13 @@ class WebSection(Domain, DocumentExtensibleTraversableMixin): ...@@ -113,11 +114,13 @@ class WebSection(Domain, DocumentExtensibleTraversableMixin):
if language: if language:
translated_path_dict = self._getTranslatedPathDict() translated_path_dict = self._getTranslatedPathDict()
try: try:
section = self[translated_path_dict[(name, language)]] section_id = translated_path_dict[(name, language)]
section = self[section_id]
except KeyError: except KeyError:
pass pass
else: else:
return section.asContext(id=name).__of__(self) if section_id != name:
return section.asContext(id=name).__of__(self)
# Register current web site physical path for later URL generation # Register current web site physical path for later URL generation
if request.get(self.web_section_key, MARKER) is MARKER: if request.get(self.web_section_key, MARKER) is MARKER:
request[self.web_section_key] = self.getPhysicalPath() request[self.web_section_key] = self.getPhysicalPath()
...@@ -177,18 +180,51 @@ class WebSection(Domain, DocumentExtensibleTraversableMixin): ...@@ -177,18 +180,51 @@ class WebSection(Domain, DocumentExtensibleTraversableMixin):
if k[0] == 'translatable_id' and v[0] == section_id} if k[0] == 'translatable_id' and v[0] == section_id}
for language in available_language_list: for language in available_language_list:
translated_section_id = translated_section_id_dict.get(language, section_id) translated_section_id = translated_section_id_dict.get(language, section_id)
checkValidId(self, translated_section_id, allow_dup=True) try:
checkValidId(self, translated_section_id, allow_dup=True)
except BadRequest:
continue
key = (translated_section_id, language) key = (translated_section_id, language)
if key in translated_path_dict: if key not in translated_path_dict:
raise ValueError('%r is used in several sections : %r' % (key, (translated_path_dict[key], section_id))) translated_path_dict[key] = section_id
translated_path_dict[key] = section_id
if translated_path_dict != self._getTranslatedPathDict(): if translated_path_dict != self._getTranslatedPathDict():
setattr(self, INTERNAL_TRANSLATED_PATH_DICT_NAME, translated_path_dict) setattr(self, INTERNAL_TRANSLATED_PATH_DICT_NAME, translated_path_dict)
self._p_changed = True
if recursive: if recursive:
for section in self.objectValues(portal_type='Web Section'): for section in self.objectValues(portal_type='Web Section'):
section.updateTranslatedPathDict(recursive=recursive) section.updateTranslatedPathDict(recursive=recursive)
security.declareProtected(Permissions.AccessContentsInformation, 'checkTranslatablePathConsistency')
def checkTranslatablePathConsistency(self, fixit=False):
error_list = []
translated_path_dict = getattr(self.getParentValue(), '_getTranslatedPathDict', lambda: {})()
id_ = self.getId()
available_language_list = self.getAvailableLanguageList()
translated_section_id_dict = {k[1]: v[1] for k, v in six.iteritems(self._getTranslationDict()) \
if k[0] == 'translatable_id' and v[0] == id_}
for language in available_language_list:
translated_section_id = translated_section_id_dict.get(language, id_)
try:
checkValidId(self, translated_section_id, allow_dup=True)
except BadRequest:
error_list.append(
(
'"${translated_path}" is not valid.',
{'translated_path': translated_section_id},
)
)
continue
key = (translated_section_id, language)
if translated_path_dict.get(key, id_) != id_:
error_list.append(
(
'"${translated_path}" for ${language} is already used in "${section}"',
{'translated_path': key[0],
'language': self.Localizer.get_language_name(key[1]),
'section': translated_path_dict[key]},
)
)
return error_list
security.declarePrivate( 'manage_beforeDelete' ) security.declarePrivate( 'manage_beforeDelete' )
def manage_beforeDelete(self, item, container): def manage_beforeDelete(self, item, container):
if item is self: if item is self:
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Script Constraint" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>constraint_type/default</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>translatable_path_constraint</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Script Constraint</string> </value>
</item>
<item>
<key> <string>script_id</string> </key>
<value> <string>checkTranslatablePathConsistency</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -1620,26 +1620,41 @@ Hé Hé Hé!""", page.asText().strip()) ...@@ -1620,26 +1620,41 @@ Hé Hé Hé!""", page.asText().strip())
) )
page2_fr.publish() page2_fr.publish()
section2.setAggregateValue(page2) section2.setAggregateValue(page2)
section2.setFrTranslatedTranslatableId('aaa')
# Only setting /fr/aaa => /bbb will conflict with /aaa having no translated path yet. # Only setting /fr/aaa => /bbb will conflict with /aaa having no translated path yet.
self.assertRaises(ValueError, self.commit) section2.setFrTranslatedTranslatableId('aaa')
self.tic()
error_list = section2.checkConsistency(filter={'constraint_type': 'default'})
self.assertEqual(1, len(error_list))
self.assertEqual(
'"aaa" for French is already used in "aaa"',
str(error_list[0].getMessage()),
)
# After setting /fr/ccc => /aaa as well, we have no conflict. # After setting /fr/ccc => /aaa as well, we have no conflict.
section1.setFrTranslatedTranslatableId('ccc') section1.setFrTranslatedTranslatableId('ccc')
self.tic() self.tic()
error_list = section2.checkConsistency(filter={'constraint_type': 'default'})
self.assertEqual(0, len(error_list))
website_absolute_url = website.absolute_url() website_absolute_url = website.absolute_url()
website_path = website.absolute_url_path() website_path = website.absolute_url_path()
# /fr/ccc/ is /aaa/ # /fr/ccc/ is /aaa/
response = self.publish(website_path + '/fr/ccc/') response = self.publish(website_path + '/fr/ccc/')
self.assertEqual(HTTP_OK, response.status) self.assertEqual(HTTP_OK, response.status)
self.assertIn('page1 in French', response.getBody()) self.assertIn('page1 in French', response.getBody())
# /fr/aaa/ is /bbb/ # /fr/aaa/ is /bbb/
response = self.publish(website_path + '/fr/aaa/') response = self.publish(website_path + '/fr/aaa/')
self.assertEqual(HTTP_OK, response.status) self.assertEqual(HTTP_OK, response.status)
self.assertIn('page2 in French', response.getBody()) self.assertIn('page2 in French', response.getBody())
# /fr/bbb/ should be redirected to /fr/aaa/ # /fr/bbb/ should be redirected to /fr/aaa/
response = self.publish(website_path + '/fr/bbb/') response = self.publish(website_path + '/fr/bbb/')
self.assertEqual(MOVED_TEMPORARILY, response.status) self.assertEqual(MOVED_TEMPORARILY, response.status)
self.assertEqual(website_absolute_url + '/fr/aaa/', response.getHeader('Location')) self.assertEqual(website_absolute_url + '/fr/aaa/', response.getHeader('Location'))
# check absolute_translated_url() # check absolute_translated_url()
with self.portal.Localizer.translationContext('fr'): with self.portal.Localizer.translationContext('fr'):
self.assertEqual(website_absolute_url + '/fr', website.absolute_translated_url()) self.assertEqual(website_absolute_url + '/fr', website.absolute_translated_url())
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
<value> <value>
<tuple> <tuple>
<string>set.*TranslatedTranslatableId</string> <string>set.*TranslatedTranslatableId</string>
<string>setId</string>
</tuple> </tuple>
</value> </value>
</item> </item>
......
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