Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6e8e05e
minimize calls of getRefObj/getLinkObj
drfho Feb 7, 2026
e8eb17b
debug code for call-counting
drfho Feb 7, 2026
7828500
added traceback for debugging
drfho Feb 8, 2026
61f5064
more traceback for debugging
drfho Feb 9, 2026
e1201ac
revoke inline-validation in zmi
drfho Feb 9, 2026
934f173
removed debug output for merge
drfho Feb 9, 2026
f94c041
Merge branch 'main' into fix_redundant_link_processing
drfho Feb 9, 2026
44aff6f
restored lines for debug output
drfho Feb 9, 2026
9481056
call getRefObj for embedded links
zmsdev Feb 10, 2026
f1b0167
call getRefObj for embedded links
zmsdev Feb 10, 2026
307580e
debug-helper: added buffer-counter for getLinkObj
drfho Feb 11, 2026
f6f97fa
Persist embed_type (attr_type)
zmsdev Feb 11, 2026
b87103b
monotonized indents of former commit
drfho Feb 11, 2026
9d69e49
fixed redundant call of getLinkObj
zmsdev Feb 12, 2026
25b6b56
Merge branch 'fix_redundant_link_processing' of https://github.com/zm…
zmsdev Feb 12, 2026
409438b
Merge branch 'main' into fix_redundant_link_processing
drfho Feb 12, 2026
d48572e
Merge branch 'main' into fix_redundant_link_processing
drfho Feb 12, 2026
b880fd5
modified validateLinkObj description
drfho Feb 13, 2026
7d6faad
embed remote objects and prepare impoved validation of ref-objects
zmsdev Feb 13, 2026
f8f06d1
prepare for merge
drfho Feb 18, 2026
bef6f77
restore debug code
drfho Feb 18, 2026
ca3b922
refact conditionioning link-validation
drfho Feb 18, 2026
51ff4b4
Merge branch 'main' into fix_redundant_link_processing
drfho Feb 18, 2026
a6bfe6a
Merge branch 'main' into fix_redundant_link_processing
drfho Feb 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions Products/zms/_objattrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,12 +570,12 @@ def getObjProperty(self, key, REQUEST={}, par=None):
datatype = obj_attr['datatype_key']
value = self.getObjAttrValue( obj_attr, REQUEST)
if value:
# Text-Fields
if datatype in _globals.DT_TEXTS:
value = self.validateInlineLinkObj(value)
# Url-Fields
if datatype == _globals.DT_URL:
value = self.validateLinkObj(value)
# Text-Fields: validate inline-links (skip in manage to avoid redundant getLinkObj calls)
if datatype in _globals.DT_TEXTS and not standard.isManagementInterface(self):
value = self.validateInlineLinkObj(value)
# Url-Fields: validate link-attributes (skip in manage to avoid redundant getLinkObj calls)
if datatype == _globals.DT_URL and not standard.isManagementInterface(self):
value = self.validateLinkObj(value)
# Executable fields.
value = standard.dt_exec(self, value)

Expand Down
65 changes: 46 additions & 19 deletions Products/zms/_zreferableitem.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
# Product Imports.
from Products.zms import standard
from zope.globalrequest import getRequest
# FOR DEBUGGING PURPOSES ONLY: import traceback to log the call stack of getLinkObj calls
import traceback

# ------------------------------------------------------------------------------
# isMailLink:
Expand Down Expand Up @@ -502,30 +504,55 @@ def getLinkObj(self, url, REQUEST=None):
i = max(url.find('#'),url.find(','))
if i > 0:
url = url[:i]
if url.find('id:') >= 0:
catalog = self.getZMSIndex().get_catalog()
q = catalog({'get_uid':url})
for r in q:
path = '%s/'%r['getPath']
#-- [ReqBuff]: Fetch buffered value from Http-Request.
reqBuffId = 'getLinkObj.%s'%url
try:
ob = self.getDocumentElement().fetchReqBuff(reqBuffId)
except:
if url.find('id:') >= 0:
catalog = self.getZMSIndex().get_catalog()
q = catalog({'get_uid':url})
for r in q:
path = '%s/'%r['getPath']
l = [x for x in path.split('/') if x]
ob = self.getRootElement()
if l:
[l.pop(0) for x in ob.getPhysicalPath() if l[0] == x]
for id in l:
ob = getattr(ob,id,None)
break
elif not url.startswith('__'):
path = url.replace('@','/content/')
l = [x for x in path.split('/') if x]
ob = self.getRootElement()
ob = self.getDocumentElement()
if l:
[l.pop(0) for x in ob.getPhysicalPath() if l[0] == x]
for id in l:
ob = getattr(ob,id,None)
break
elif not url.startswith('__'):
path = url.replace('@','/content/')
l = [x for x in path.split('/') if x]
ob = self.getDocumentElement()
if l:
[l.pop(0) for x in ob.getPhysicalPath() if l[0] == x]
for id in l:
ob = getattr(ob,id,None)
# Prepare request
ids = self.getPhysicalPath()
if ob is not None and ob.id not in ids:
ob.set_request_context(request, ref_params)
#-- [ReqBuff]: Store value in buffer of Http-Request.
self.getDocumentElement().storeReqBuff(reqBuffId, ob)
# Prepare request (only if ref_params are provided)
if ob is not None and ref_params:
ids = self.getPhysicalPath()
if ob.id not in ids:
ob.set_request_context(request, ref_params)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# DEBUG: logging/counting getLinkObj calls
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
request.set('getLinkObj_counter', request.get('getLinkObj_counter', 0) + 1)
# show traceback in debugging output to identify which function is calling getLinkObj and causing multiple calls
traceback_stack = []
for frame in reversed(traceback.extract_stack()[-5:-2]):
traceback_stack.append('%s:%s:%s' % (str(frame.filename).split('/')[-1], frame.lineno, frame.name))
standard.writeStdout(self, '%d. [getLinkObj] %s, ID=%s, ref_params=%s\n...was called from:\n\t%s\n'%(
request.get('getLinkObj_counter', 0),
url,
ob.id if ob is not None else None,
ref_params,
'\n\t'.join(traceback_stack)
Copy link
Contributor Author

@drfho drfho Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zmsdev: the traceback stack now shows the last 3 function calls ending with the call of getLinkObj(). The example shows 8 Linkobjects that induce each about 8 function calls for creating the rendering. 51 of 66 functions calls are delivered from the new request-buffer.

Image

)
)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return ob


Expand Down
2 changes: 1 addition & 1 deletion Products/zms/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2025.9.1+b976ca4
2025.9.1+e8eb17b
8 changes: 7 additions & 1 deletion Products/zms/zmslinkelement.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,12 +193,18 @@ def getRef(self):
# ZMSLinkElement.getRefObj:
# --------------------------------------------------------------------------
def getRefObj(self):
#-- [ReqBuff]: Fetch buffered value from Http-Request.
docelmnt = self.getDocumentElement()
reqBuffId = 'getRefObj.%s'%self.get_uid()
try: return docelmnt.fetchReqBuff(reqBuffId)
except: pass
ref_obj = self.getLinkObj(self.getRef())
if ref_obj == self:
ref_obj = None
if ref_obj is not None and ref_obj.meta_type == 'ZMSLinkElement':
ref_obj = ref_obj.getRefObj()
return ref_obj
#-- [ReqBuff]: Returns value and stores it in buffer of Http-Request.
return docelmnt.storeReqBuff(reqBuffId, ref_obj)


# --------------------------------------------------------------------------
Expand Down