Skip to content

Commit

Permalink
Add portal_type title (#1355)
Browse files Browse the repository at this point in the history
* Add type title to content serializer

* Add portal_type title to serializers

* Update tests to include the new 'type' field

* Translate type

* Add changelog

* ref #1322: add  portal_type id as '@type' to types GET api

* Renamed type to type_name

* Rename type to type_name in tests

* also support portal_type in parent field in dx contents, fix tests

* fix(): rename method get_portal_type, remove type_name explicit assignment

* refactor(summarySerializer): set type_name in defaultSummarySerializer

* refactor(utils): use lookup_fti for getting DX fti efficiently

* fix(): remove unused imports

* fix: unused import

* Update news/1355.feature

Co-authored-by: David Glick <david@glicksoftware.com>

* fix(code-analysis): re-format to add whitespace

* rename(type_name) -> type-title

* Update src/plone/restapi/services/types/get.py

Co-authored-by: David Glick <david@glicksoftware.com>

* change(types): @type -> id, fix tests

* Refactor get_portal_type_title request getter

* Cleanup

---------

Co-authored-by: Alin Voinea <contact@avoinea.com>
Co-authored-by: Nilesh <nileshgulia@gmail.com>
Co-authored-by: David Glick <david@glicksoftware.com>
  • Loading branch information
4 people committed May 18, 2023
1 parent d40e0bf commit 04e6982
Show file tree
Hide file tree
Showing 50 changed files with 290 additions and 106 deletions.
1 change: 1 addition & 0 deletions news/1355.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add portal_type title (`type_title`) to content response [razvanMiu][nileshgulia1]
5 changes: 3 additions & 2 deletions src/plone/restapi/serializer/dxcontent.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from plone.restapi.serializer.expansion import expandable_elements
from plone.restapi.serializer.nextprev import NextPrevious
from plone.restapi.services.locking import lock_info
from plone.restapi.serializer.utils import get_portal_type_title
from plone.rfc822.interfaces import IPrimaryFieldInfo
from plone.supermodel.utils import mergedTaggedValueDict
from Products.CMFCore.utils import getToolByName
Expand Down Expand Up @@ -62,11 +63,13 @@ def __call__(self, version=None, include_items=True):
parent_summary = getMultiAdapter(
(parent, self.request), ISerializeToJsonSummary
)()

result = {
# '@context': 'http://www.w3.org/ns/hydra/context.jsonld',
"@id": obj.absolute_url(),
"id": obj.id,
"@type": obj.portal_type,
"type_title": get_portal_type_title(obj.portal_type),
"parent": parent_summary,
"created": json_compatible(obj.created()),
"modified": json_compatible(obj.modified()),
Expand Down Expand Up @@ -101,7 +104,6 @@ def __call__(self, version=None, include_items=True):
read_permissions = mergedTaggedValueDict(schema, READ_PERMISSIONS_KEY)

for name, field in getFields(schema).items():

if not self.check_permission(read_permissions.get(name), obj):
continue

Expand Down Expand Up @@ -203,7 +205,6 @@ def __call__(self):
read_permissions = mergedTaggedValueDict(schema, READ_PERMISSIONS_KEY)

for name, field in getFields(schema).items():

if not self.check_permission(read_permissions.get(name), self.context):
continue

Expand Down
3 changes: 3 additions & 0 deletions src/plone/restapi/serializer/nextprev.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from Acquisition import aq_parent
from plone.app.dexterity.behaviors.nextprevious import NextPreviousBase
from plone.registry.interfaces import IRegistry
from plone.restapi.serializer.utils import get_portal_type_title
from zope.component import getUtility


Expand Down Expand Up @@ -40,6 +41,7 @@ def next(self):
return {
"@id": data["url"].lstrip("/view"),
"@type": data["portal_type"],
"type_title": get_portal_type_title(data.get("portal_type")),
"title": data["title"],
"description": data["description"],
}
Expand All @@ -56,6 +58,7 @@ def previous(self):
return {
"@id": data["url"].lstrip("/view"),
"@type": data["portal_type"],
"type_title": get_portal_type_title(data.get("portal_type")),
"title": data["title"],
"description": data["description"],
}
3 changes: 2 additions & 1 deletion src/plone/restapi/serializer/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from plone.restapi.serializer.converters import json_compatible
from plone.restapi.serializer.expansion import expandable_elements
from plone.restapi.services.locking import lock_info
from plone.restapi.serializer.utils import get_portal_type_title
from plone.supermodel.utils import mergedTaggedValueDict
from Products.CMFCore.utils import getToolByName
from zope.component import adapter
Expand Down Expand Up @@ -62,6 +63,7 @@ def __call__(self, version=None):
"@id": self.context.absolute_url(),
"id": self.context.id,
"@type": "Plone Site",
"type_title": get_portal_type_title("Plone Site"),
"title": self.context.Title(),
"parent": {},
"is_folderish": True,
Expand All @@ -81,7 +83,6 @@ def __call__(self, version=None):
read_permissions = mergedTaggedValueDict(schema, READ_PERMISSIONS_KEY)

for name, field in getFields(schema).items():

if not self.check_permission(
read_permissions.get(name), self.context
):
Expand Down
15 changes: 7 additions & 8 deletions src/plone/restapi/serializer/summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from plone.restapi.interfaces import IJSONSummarySerializerMetadata
from plone.restapi.interfaces import ISerializeToJsonSummary
from plone.restapi.serializer.converters import json_compatible
from plone.restapi.serializer.utils import get_portal_type_title
from Products.CMFCore.utils import getToolByName
from Products.CMFCore.WorkflowCore import WorkflowException
from zope.component import adapter
Expand All @@ -15,13 +16,7 @@
@implementer(IJSONSummarySerializerMetadata)
class JSONSummarySerializerMetadata:
def default_metadata_fields(self):
return {
"@id",
"@type",
"description",
"review_state",
"title",
}
return {"@id", "@type", "description", "review_state", "title", "type_title"}

def field_accessors(self):
return {
Expand Down Expand Up @@ -95,7 +90,10 @@ def __call__(self):
if field.startswith("_") or field in self.blocklisted_attributes:
continue
accessor = self.field_accessors.get(field, field)
value = getattr(obj, accessor, None)
if field == "type_title":
value = get_portal_type_title(self.context.portal_type)
else:
value = getattr(obj, accessor, None)
try:
if callable(value):
value = value()
Expand Down Expand Up @@ -140,6 +138,7 @@ def __call__(self):
{
"@id": self.context.absolute_url(),
"@type": self.context.portal_type,
"type_title": get_portal_type_title(self.context.portal_type),
"title": self.context.title,
"description": self.context.description,
}
Expand Down
11 changes: 11 additions & 0 deletions src/plone/restapi/serializer/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from plone.dexterity.schema import lookup_fti
from plone.app.uuid.utils import uuidToCatalogBrain
from plone.restapi.interfaces import IObjectPrimaryFieldTarget
from zope.component import queryMultiAdapter
from zope.i18n import translate
from zope.globalrequest import getRequest

import re

Expand Down Expand Up @@ -38,3 +41,11 @@ def uid_to_url(path):
if a_href:
return a_href
return href


def get_portal_type_title(portal_type):
fti = lookup_fti(portal_type)
request = getRequest()
if request:
return translate(getattr(fti, "Title", lambda: portal_type)(), context=request)
return getattr(fti, "Title", lambda: portal_type)()
3 changes: 1 addition & 2 deletions src/plone/restapi/services/contextnavigation/get.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,6 @@ def getNavTree(self):

class NavigationPortletRenderer:
def __init__(self, context, request, data):

self.context = context
self.request = request
self.data = data
Expand Down Expand Up @@ -251,7 +250,7 @@ def heading_link_target(self):
# Go to the item /view we have chosen as root item
return nav_root.absolute_url()

def root_type_name(self):
def root_type_title(self):
root = self.getNavRoot()
return queryUtility(IIDNormalizer).normalize(root.portal_type)

Expand Down
1 change: 1 addition & 0 deletions src/plone/restapi/services/types/get.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ def __call__(self, expand=False):
result["types"] = [
{
"@id": f"{portal_url}/@types/{fti.getId()}",
"id": fti.getId(),
"title": translate(fti.Title(), context=self.request),
"addable": fti.getId() in allowed_types if can_add else False,
"immediately_addable": fti.getId() in immediately_types
Expand Down
15 changes: 10 additions & 5 deletions src/plone/restapi/tests/http-examples/batching.resp
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,40 @@ Content-Type: application/json
"@type": "Folder",
"description": "",
"review_state": "private",
"title": "Folder"
"title": "Folder",
"type_title": "Folder"
},
{
"@id": "http://localhost:55001/plone/folder/doc-1",
"@type": "Document",
"description": "",
"review_state": "private",
"title": "Document 1"
"title": "Document 1",
"type_title": "Page"
},
{
"@id": "http://localhost:55001/plone/folder/doc-2",
"@type": "Document",
"description": "",
"review_state": "private",
"title": "Document 2"
"title": "Document 2",
"type_title": "Page"
},
{
"@id": "http://localhost:55001/plone/folder/doc-3",
"@type": "Document",
"description": "",
"review_state": "private",
"title": "Document 3"
"title": "Document 3",
"type_title": "Page"
},
{
"@id": "http://localhost:55001/plone/folder/doc-4",
"@type": "Document",
"description": "",
"review_state": "private",
"title": "Document 4"
"title": "Document 4",
"type_title": "Page"
}
],
"items_total": 8
Expand Down
19 changes: 13 additions & 6 deletions src/plone/restapi/tests/http-examples/collection.resp
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,24 @@ Content-Type: application/json
"@type": "Document",
"description": "Congratulations! You have successfully installed Plone.",
"review_state": "private",
"title": "Welcome to Plone"
"title": "Welcome to Plone",
"type_title": "Page"
},
{
"@id": "http://localhost:55001/plone/doc1",
"@type": "Document",
"description": "",
"review_state": "private",
"title": "Document 1"
"title": "Document 1",
"type_title": "Page"
},
{
"@id": "http://localhost:55001/plone/doc2",
"@type": "Document",
"description": "",
"review_state": "private",
"title": "Document 2"
"title": "Document 2",
"type_title": "Page"
}
],
"items_total": 3,
Expand All @@ -95,19 +98,22 @@ Content-Type: application/json
"@id": "http://localhost:55001/plone/doc1",
"@type": "Document",
"description": "",
"title": "Document 1"
"title": "Document 1",
"type_title": "Page"
},
"parent": {
"@id": "http://localhost:55001/plone",
"@type": "Plone Site",
"description": "",
"title": "Plone site"
"title": "Plone site",
"type_title": "Plone Site"
},
"previous_item": {
"@id": "http://localhost:55001/plone/front-page",
"@type": "Document",
"description": "Congratulations! You have successfully installed Plone.",
"title": "Welcome to Plone"
"title": "Welcome to Plone",
"type_title": "Page"
},
"query": [
{
Expand All @@ -124,6 +130,7 @@ Content-Type: application/json
"subjects": [],
"text": null,
"title": "My Collection",
"type_title": "Collection",
"version": "current",
"working_copy": null,
"working_copy_of": null
Expand Down

0 comments on commit 04e6982

Please sign in to comment.