Repository: plone/Products.CMFPlone

Issue:
exclude_from_nav and show_excluded_items are not handled correctly in portal_tabs_view
### What I did:

Create a folder on top level and exclude id from navigation

### What I expect to happen:

the folder should disappear from global navigation **when I'm not inside it's context**

### What actually happened:

the folder is always in the navigation

### What version of Plone/ Addons I am using:

plone 5.2rc2

### REASON:

I'm fixing a bug found here: https://github.com/plone/plone.app.layout/issues/190
which leads to the same result in `portal_tabs_view` here https://github.com/plone/Products.CMFPlone/blob/master/Products/CMFPlone/browser/navigation.py#L151-L153

if `show_excluded_items` is activated (which actually is the default setting) every item is shown regardless of `exclude_from_nav` setting. But what the setting claims is to show the excluded item only if you're inside of it.

PR is in preparation...


Discussion:

Resolving patch:
diff --git a/Products/CMFPlone/browser/navigation.py b/Products/CMFPlone/browser/navigation.py
--- a/Products/CMFPlone/browser/navigation.py
+++ b/Products/CMFPlone/browser/navigation.py
@@ -72,7 +72,7 @@ def siteMap(self):
 class CatalogNavigationTabs(BrowserView):
 
     def _getNavQuery(self):
-                # check whether we only want actions
+        # check whether we only want actions
         registry = getUtility(IRegistry)
         navigation_settings = registry.forInterface(
             INavigationSchema,
@@ -101,6 +101,9 @@ def _getNavQuery(self):
 
         query['is_default_page'] = False
 
+        if not navigation_settings.show_excluded_items:
+            query['exclude_from_nav'] = False
+
         if not navigation_settings.nonfolderish_tabs:
             query['is_folderish'] = True
 
@@ -146,11 +149,13 @@ def _get_url(item):
                 return (get_id(item), item.getRemoteUrl)
             return get_view_url(item)
 
+        context_path = '/'.join(context.getPhysicalPath())
+
         # now add the content to results
         for item in rawresult:
-            if not navigation_settings.show_excluded_items:
-                if item.exclude_from_nav:
-                    continue
+            if item.exclude_from_nav and not context_path.startswith(item.getPath()):  # noqa: E501
+                # skip excluded items if they're not in our context path
+                continue
             cid, item_url = _get_url(item)
             data = {
                 'name': utils.pretty_title_or_id(context, item),


Test patch:
diff --git a/Products/CMFPlone/tests/testNavigationView.py b/Products/CMFPlone/tests/testNavigationView.py
--- a/Products/CMFPlone/tests/testNavigationView.py
+++ b/Products/CMFPlone/tests/testNavigationView.py
@@ -596,28 +596,25 @@ def testDisableFolderTabs(self):
         self.assertEqual(tabs, [])
 
     def testTabsExcludeItemsWithExcludeProperty(self):
-        # Make sure that items witht he exclude_from_nav property are purged
-        view = self.view_class(self.portal, self.request.clone())
-        tabs = view.topLevelTabs(actions=[])
-        orig_len = len(tabs)
         self.portal.folder2.exclude_from_nav = True
         self.portal.folder2.reindexObject()
 
-        # For the moment nothing changes because the default for
-        # plone.show_excluded_items is True
-        view = self.view_class(self.portal, self.request.clone())
+        # if we're not in context of the excluded item it should disappear
+        view = self.view_class(self.portal, self.request)
+        tabs = view.topLevelTabs(actions=[])
+        tab_names = [t['id'] for t in tabs]
+        self.assertNotIn('folder2', tab_names)
+
+        # but if we're inside, it should be visible
+        view = self.view_class(self.portal.folder2, self.request)
         tabs = view.topLevelTabs(actions=[])
-        self.assertTrue(tabs)
-        self.assertEqual(len(tabs), orig_len)
         tab_names = [t['id'] for t in tabs]
         self.assertIn('folder2', tab_names)
 
         # Now we flip the setting for plone.show_excluded_items
         self.navigation_settings.show_excluded_items = False
-        view = self.view_class(self.portal, self.request)
+        view = self.view_class(self.portal.folder2, self.request)
         tabs = view.topLevelTabs(actions=[])
-        self.assertTrue(tabs)
-        self.assertEqual(len(tabs), orig_len - 1)
         tab_names = [t['id'] for t in tabs]
         self.assertNotIn('folder2', tab_names)