plone.restapi/expansion: Add navigation and breadcrumbs as top-level services.

Timo Stollenwerk <jenkins-z4DKO/[email protected]>
Newsgroups gmane.comp.web.zope.plone.cvs
Message-ID <[email protected]>
Repository: plone.restapi
Branch: refs/heads/expansion
Date: 2017-07-16T12:05:47+02:00
Author: Timo Stollenwerk (tisto) <[email protected]>
Commit: https://github.com/plone/plone.restapi/commit/9ddd322df0634573aa2554a53c9445726ef884e1

Add navigation and breadcrumbs as top-level services.

Files changed:
A src/plone/restapi/services/breadcrumbs/__init__.py
A src/plone/restapi/services/breadcrumbs/configure.zcml
A src/plone/restapi/services/breadcrumbs/get.py
A src/plone/restapi/services/navigation/__init__.py
A src/plone/restapi/services/navigation/configure.zcml
A src/plone/restapi/services/navigation/get.py
A src/plone/restapi/tests/test_services_breadcrumbs.py
A src/plone/restapi/tests/test_services_navigation.py
M CHANGES.rst
M src/plone/restapi/services/configure.zcml

diff --git a/CHANGES.rst b/CHANGES.rst
index 9997ba8f..c3b2fd8e 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,7 +4,11 @@ Changelog
 1.0a20 (unreleased)
 -------------------
 
-- Nothing changed yet.
+New Features:
+
+- Add navigation and breadcrumbs as top-level services. Deprecate navigation
+  and breadcrumbs as components.
+  [timo]
 
 
 1.0a19 (2017-06-25)
diff --git a/src/plone/restapi/services/breadcrumbs/__init__.py b/src/plone/restapi/services/breadcrumbs/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/plone/restapi/services/breadcrumbs/configure.zcml b/src/plone/restapi/services/breadcrumbs/configure.zcml
new file mode 100644
index 00000000..0c39c889
--- /dev/null
+++ b/src/plone/restapi/services/breadcrumbs/configure.zcml
@@ -0,0 +1,13 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:plone="http://namespaces.plone.org/plone">
+
+  <plone:service
+    method="GET"
+    for="zope.interface.Interface"
+    factory=".get.BreadcrumbsGet"
+    name="@breadcrumbs"
+    permission="zope2.View"
+    />
+
+</configure>
diff --git a/src/plone/restapi/services/breadcrumbs/get.py b/src/plone/restapi/services/breadcrumbs/get.py
new file mode 100644
index 00000000..b8d9b97a
--- /dev/null
+++ b/src/plone/restapi/services/breadcrumbs/get.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+from plone.restapi.services import Service
+from zope.component import getMultiAdapter
+
+
+class BreadcrumbsGet(Service):
+
+    def reply(self):
+        breadcrumbs_view = getMultiAdapter((self.context, self.request),
+                                           name="breadcrumbs_view")
+        result = []
+        for crumb in breadcrumbs_view.breadcrumbs():
+            result.append({
+                'title': crumb['Title'],
+                'url': crumb['absolute_url']
+            })
+        return result
diff --git a/src/plone/restapi/services/configure.zcml b/src/plone/restapi/services/configure.zcml
index ac5d8a69..a36166fe 100644
--- a/src/plone/restapi/services/configure.zcml
+++ b/src/plone/restapi/services/configure.zcml
@@ -2,12 +2,14 @@
     xmlns="http://namespaces.zope.org/zope">
 
   <include package=".auth" />
+  <include package=".breadcrumbs"/>
   <include package=".components"/>
   <include package=".content"/>
   <include package=".copymove"/>
   <include package=".discussion"/>
   <include package=".groups"/>
   <include package=".history"/>
+  <include package=".navigation"/>
   <include package=".principals"/>
   <include package=".registry"/>
   <include package=".roles"/>
diff --git a/src/plone/restapi/services/navigation/__init__.py b/src/plone/restapi/services/navigation/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/src/plone/restapi/services/navigation/configure.zcml b/src/plone/restapi/services/navigation/configure.zcml
new file mode 100644
index 00000000..05e200e4
--- /dev/null
+++ b/src/plone/restapi/services/navigation/configure.zcml
@@ -0,0 +1,13 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:plone="http://namespaces.plone.org/plone">
+
+  <plone:service
+    method="GET"
+    for="zope.interface.Interface"
+    factory=".get.NavigationGet"
+    name="@navigation"
+    permission="zope2.View"
+    />
+
+</configure>
diff --git a/src/plone/restapi/services/navigation/get.py b/src/plone/restapi/services/navigation/get.py
new file mode 100644
index 00000000..a2bf0504
--- /dev/null
+++ b/src/plone/restapi/services/navigation/get.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+from plone.restapi.services import Service
+from zope.component import getMultiAdapter
+
+
+class NavigationGet(Service):
+
+    def reply(self):
+        tabs = getMultiAdapter((self.context, self.request),
+                               name="portal_tabs_view")
+        result = []
+        for tab in tabs.topLevelTabs():
+            result.append({
+                'title': tab.get('title', tab.get('name')),
+                'url': tab['url'] + ''
+            })
+        return result
diff --git a/src/plone/restapi/tests/test_services_breadcrumbs.py b/src/plone/restapi/tests/test_services_breadcrumbs.py
new file mode 100644
index 00000000..59dfc008
--- /dev/null
+++ b/src/plone/restapi/tests/test_services_breadcrumbs.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+from plone.app.testing import setRoles
+from plone.app.testing import SITE_OWNER_NAME
+from plone.app.testing import SITE_OWNER_PASSWORD
+from plone.app.testing import TEST_USER_ID
+from plone.dexterity.utils import createContentInContainer
+from plone.restapi.testing import PLONE_RESTAPI_DX_FUNCTIONAL_TESTING
+from plone.restapi.testing import RelativeSession
+
+import transaction
+import unittest
+
+
+class TestServicesBreadcrumbs(unittest.TestCase):
+
+    layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING
+
+    def setUp(self):
+        self.app = self.layer['app']
+        self.portal = self.layer['portal']
+        self.portal_url = self.portal.absolute_url()
+        setRoles(self.portal, TEST_USER_ID, ['Manager'])
+
+        self.api_session = RelativeSession(self.portal_url)
+        self.api_session.headers.update({'Accept': 'application/json'})
+        self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD)
+
+        self.folder = createContentInContainer(
+            self.portal, u'Folder',
+            id=u'folder',
+            title=u'Some Folder')
+        createContentInContainer(
+            self.folder, u'Document',
+            id=u'doc1',
+            title=u'A document')
+        transaction.commit()
+
+    def test_breadcrumbs(self):
+        response = self.api_session.get('/folder/doc1/@breadcrumbs')
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(
+            response.json(),
+            [{
+                u'url': u'http://localhost:55001/plone/folder',
+                u'title': u'Some Folder'
+            }, {
+                u'url': u'http://localhost:55001/plone/folder/doc1',
+                u'title': u'A document'
+            }]
+        )
diff --git a/src/plone/restapi/tests/test_services_navigation.py b/src/plone/restapi/tests/test_services_navigation.py
new file mode 100644
index 00000000..ad55a612
--- /dev/null
+++ b/src/plone/restapi/tests/test_services_navigation.py
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+from plone.app.testing import setRoles
+from plone.app.testing import SITE_OWNER_NAME
+from plone.app.testing import SITE_OWNER_PASSWORD
+from plone.app.testing import TEST_USER_ID
+from plone.dexterity.utils import createContentInContainer
+from plone.restapi.testing import PLONE_RESTAPI_DX_FUNCTIONAL_TESTING
+from plone.restapi.testing import RelativeSession
+
+import transaction
+import unittest
+
+
+class TestServicesNavigation(unittest.TestCase):
+
+    layer = PLONE_RESTAPI_DX_FUNCTIONAL_TESTING
+
+    def setUp(self):
+        self.app = self.layer['app']
+        self.portal = self.layer['portal']
+        self.portal_url = self.portal.absolute_url()
+        setRoles(self.portal, TEST_USER_ID, ['Manager'])
+
+        self.api_session = RelativeSession(self.portal_url)
+        self.api_session.headers.update({'Accept': 'application/json'})
+        self.api_session.auth = (SITE_OWNER_NAME, SITE_OWNER_PASSWORD)
+
+        self.folder = createContentInContainer(
+            self.portal, u'Folder',
+            id=u'folder',
+            title=u'Some Folder')
+        createContentInContainer(
+            self.folder, u'Document',
+            id=u'doc1',
+            title=u'A document')
+        transaction.commit()
+
+    def test_navigation(self):
+        response = self.api_session.get('/folder/@navigation')
+
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(
+            response.json(),
+            [
+                {
+                    u'title': u'Home',
+                    u'url': u'http://localhost:55001/plone'
+                },
+                {
+                    u'title': u'Some Folder',
+                    u'url': u'http://localhost:55001/plone/folder'
+                }
+            ]
+        )



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.