Repository: plone/Products.CMFPlone

Issue:
Sortable title cuts the title without a valid reason
In Plone 5.2 and also in 6 the sortable_title index is a FieldIndex in the catalog used to sort contents based on title. But the sortable_title method in portal_catalog just cuts the title in the middle if the title is longer that 40 chars. So if you have very similar long titles but with differences after the 12th char, the sorting on `sortable_title` (as a concept) is wrong.

Master:
https://github.com/plone/Products.CMFPlone/blob/master/Products/CMFPlone/CatalogTool.py#L165-L184

https://github.com/plone/Products.CMFPlone/blob/5.2.x/Products/CMFPlone/CatalogTool.py#L190-L211

Is this behavior intended? And if so why?



Discussion:

Resolving patch:
diff --git a/Products/CMFPlone/CatalogTool.py b/Products/CMFPlone/CatalogTool.py
--- a/Products/CMFPlone/CatalogTool.py
+++ b/Products/CMFPlone/CatalogTool.py
@@ -49,7 +49,6 @@
 
 _marker = object()
 
-MAX_SORTABLE_TITLE = 40
 DENIED_INTERFACES = frozenset((
     'AccessControl.interfaces.IOwned',
     'AccessControl.interfaces.IPermissionMappingSupport',
@@ -175,11 +174,6 @@ def sortable_title(obj):
             sortabletitle = mapUnicode(safe_text(title)).lower().strip()
             # Replace numbers with zero filled numbers
             sortabletitle = num_sort_regex.sub(zero_fill, sortabletitle)
-            # Truncate to prevent bloat, take bits from start and end
-            if len(sortabletitle) > MAX_SORTABLE_TITLE:
-                start = sortabletitle[:(MAX_SORTABLE_TITLE - 13)]
-                end = sortabletitle[-10:]
-                sortabletitle = start + '...' + end
             return sortabletitle
     return ''
 


Test patch:
diff --git a/Products/CMFPlone/tests/testCatalogTool.py b/Products/CMFPlone/tests/testCatalogTool.py
--- a/Products/CMFPlone/tests/testCatalogTool.py
+++ b/Products/CMFPlone/tests/testCatalogTool.py
@@ -147,7 +147,7 @@ def testExpiresDateNotInSchema(self):
         self.assertFalse('ExpiresDate' in self.catalog.schema())
 
     def testIs_Default_PageIsBooleanIndex(self):
-        # sortable_title should be a BooleanIndex
+        # is_default_page should be a BooleanIndex
         self.assertEqual(
             self.catalog.Indexes['is_default_page'].__class__.__name__,
             'BooleanIndex')
@@ -547,12 +547,21 @@ def afterSetUp(self):
         self.folder.doc5.setTitle('Document 2')
         self.folder.invokeFactory('Document', id='doc6', text=RichTextValue('bar', 'text/html', 'text/x-html-safe'))
         self.folder.doc6.setTitle('DOCUMENT 4')
+
+        self.folder.invokeFactory('Document', id="doc7")
+        self.folder.doc7.setTitle('Long titles used to be truncated, but we changed this, see issue 3690. 0002')
+
+        self.folder.invokeFactory('Document', id="doc8")
+        self.folder.doc8.setTitle('Long titles used to be truncated, but we changed this, see issue 3690. 0001')
+
         self.folder.doc.reindexObject()
         self.folder.doc2.reindexObject()
         self.folder.doc3.reindexObject()
         self.folder.doc4.reindexObject()
         self.folder.doc5.reindexObject()
         self.folder.doc6.reindexObject()
+        self.folder.doc7.reindexObject()
+        self.folder.doc8.reindexObject()
 
     def testSortMultipleColumns(self):
         path = '/'.join(self.folder.getPhysicalPath())
@@ -567,6 +576,8 @@ def testSortMultipleColumns(self):
                 '/plone/Members/test_user_1_/doc5',
                 '/plone/Members/test_user_1_/doc6',
                 '/plone/Members/test_user_1_/doc4',
+                '/plone/Members/test_user_1_/doc8',
+                '/plone/Members/test_user_1_/doc7',
                 '/plone/Members/test_user_1_'
             ],
         )
@@ -580,6 +591,8 @@ def testSortMultipleColumns(self):
                 '/plone/Members/test_user_1_/doc4',
                 '/plone/Members/test_user_1_/doc5',
                 '/plone/Members/test_user_1_/doc6',
+                '/plone/Members/test_user_1_/doc7',
+                '/plone/Members/test_user_1_/doc8',
                 '/plone/Members/test_user_1_',
             ]
         )
@@ -614,6 +627,13 @@ def testSortableTitleOutput(self):
 
         self.assertEqual(wrapped.sortable_title, '0012 document 0025')
 
+    def testSortableTitleInLongTitles(self):
+        doc = self.folder.doc7
+        wrapped = IndexableObjectWrapper(doc, self.portal.portal_catalog)
+
+        self.assertEqual(wrapped.sortable_title, 'long titles used to be truncated, but we changed this, see issue 3690. 0002')
+
+
     def testSortableNonASCIITitles(self):
         # test a utf-8 encoded string gets properly unicode converted
         # sort must ignore accents
@@ -651,7 +671,7 @@ def testSortableLongCommonPrefix(self):
         doc.setTitle(title)
         wrapped = IndexableObjectWrapper(doc, self.portal.portal_catalog)
         self.assertEqual(wrapped.sortable_title,
-                         'some documents have too lon... 0001.jpeg')
+                         'some documents have too long a name and only differ at the very end - like 0001.jpeg')
 
 
 class TestFolderCataloging(PloneTestCase):