Skip to content

Commit

Permalink
applied some UniBE features (#314)
Browse files Browse the repository at this point in the history
* feat(ZMI): hide redirects in object tree
* feat(ZMS): add minimal_init flag to initZMS
* feat(zms): Added standard.is_conf_enabled()
* feat(zms): Added Python version to system info
* feat(zmslog): Added feature toggle to set root node
* feat(zmslog): replace hard-coded log filename with the path defined in zope.ini
* feat(zmi): Added indicator for visibility and redirects to breadcrumbs
  • Loading branch information
cmeier76 authored Oct 3, 2024
1 parent 0e13c11 commit b9d72c5
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 52 deletions.
1 change: 1 addition & 0 deletions Products/zms/_confmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ def getConfPropertiesDefaults(self):
{'key':'ZMS.input.file.plugin','title':'File.upload input','desc':'ZMS can use custom input-fields for file-upload.','datatype':'string','options':['input_file', 'jquery_upload'],'default':'input_file'},
{'key':'ZMS.input.file.maxlength','title':'File.upload maxlength','desc':'ZMS can limit the maximum upload-file size to the given value (in Bytes).','datatype':'string'},
{'key':'ZMS.input.image.maxlength','title':'Image.upload maxlength','desc':'ZMS can limit the maximum upload-image size to the given value (in Bytes).','datatype':'string'},
{'key':'ZMS.log.root','title':'ZMS.log.root','desc':'Use ZMSLog at absolute root node instead of current portal master','datatype':'boolean'},
{'key':'ZMSGraphic.superres','title':'Image superres-attribute','desc':'Super-resolution attribute for ZMS standard image-objects.','datatype':'boolean','default':0},
{'key':'ZCatalog.TextIndexType','title':'Search with TextIndex-type','desc':'Use specified TextIndex-type (default: ZCTextIndex)','datatype':'string','default':'ZCTextIndex'},
{'key':'ZMSIndexZCatalog.ObjectImported.reindex','title':'Reindex ZMSIndex on content import','desc':'Please be aware that activating implicit ZMSIndex-resync on content import can block bigger sites for a while','datatype':'boolean','default':0},
Expand Down
4 changes: 4 additions & 0 deletions Products/zms/_deprecatedapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,10 @@ def getLangFmtDate(self, t, lang=None, fmt_str='SHORTDATETIME_FMT'):
warn(self, 'getLangFmtDate', 'Products.zms.standard.getLangFmtDate')
return standard.getLangFmtDate(self, t, lang, fmt_str)

def isFeatureEnabled(self, feature=''):
warn(self, 'isFeatureEnabled', 'Products.zms.standard.is_conf_enabled')
return standard.is_conf_enabled(self, feature)

# --------------------------------------------------------------------------
# ZMSObject.ajaxGetNodes:
# --------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1290,6 +1290,10 @@ ZMIObjectTree.prototype.addPages = function(nodes) {
var css = [ node.is_page ? 'is_page' : 'is_page_element' ];
var callback = that.p['toggleClick.callback'];

if ((node.titlealt.toUpperCase().search('REDIRECT') > -1) &&
(node.attr_dc_identifier_url_redirect &&
node.attr_dc_identifier_url_redirect.trim() != '')) return;

if (node.meta_id == 'ZMSGraphic' && link_url) {
link_url = `<img data-id=&quot;${data_id}&quot; src=&quot;${link_url}&quot;>`;
} else if (node.meta_id == 'ZMSFile' && link_url) {
Expand Down
29 changes: 26 additions & 3 deletions Products/zms/standard.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@

security.declarePublic('pybool')
def pybool(v):
return v in [True,'true','True',1]
return v in [True,'true','True',1,'1']

security.declarePublic('pystr')
def pystr(v, encoding='utf-8', errors='strict'):
Expand Down Expand Up @@ -373,11 +373,10 @@ def get_installed_packages(pip_cmd='freeze'):
}
cmd = pip_cmds.get(pip_cmd,'freeze')
pth = getPACKAGE_HOME().rsplit('/lib/')[0] + '/bin'
packages = ''
output = subprocess.Popen(pth + cmd,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
shell=True, cwd=pth, universal_newlines=True)
packages = f'# {pth}{cmd}\n\n{output.communicate()[0].strip()}'
packages = f'# {pth}{cmd}\n\nPython {sys.version}\n\n{output.communicate()[0].strip()}'
return packages


Expand Down Expand Up @@ -1104,6 +1103,8 @@ def getLog(context):
zms_log = getattr(context, 'zms_log', None)
if zms_log is None:
zms_log = getattr(context.getPortalMaster(), 'zms_log', None)
if is_conf_enabled(context, 'ZMS.log.root'):
zms_log = getattr(context.breadcrumbs_obj_path()[0], 'zms_log', None)
request.set('ZMSLOG', zms_log)
return zms_log

Expand Down Expand Up @@ -2563,6 +2564,28 @@ def raiseError(error_type, error_value):
"""
raise getattr(zExceptions,error_type)(error_value)


security.declarePublic('is_conf_enabled')
def is_conf_enabled(context, setting):
"""
Returns True if given setting is activated in system properties (= in [True,'true','True',1,'1'])
or given setting is found in system property ZMS.Features.enabled (either surrounded by % or not)
in current client or inherited from portal masters
PLEASE NOTE: System properties with prefix ASP.* are not inherited in portal clients
"""
conf_property = context.getConfProperty(setting, None)

if conf_property is None:
features_enabled = context.getConfProperty('ZMS.Features.enabled', None)
if features_enabled is not None:
features = features_enabled.replace('%', '').replace(',', ';').split(';')
if len([x for x in features if x.strip() == setting.replace('%', '').strip()]) > 0:
return True
return False

return pybool(conf_property)


class initutil(object):
"""Define the initialize() util."""

Expand Down
42 changes: 38 additions & 4 deletions Products/zms/zms.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def importTheme(self, theme):
# A new ZMS node can be initalized as a stand-alone client (master) or
# as subordinated client acquiring content models and sharing the zmsindex.
# Use a request variable 'acquire' = 1 to initalize ZMS as a client
def initZMS(self, id, titlealt, title, lang, manage_lang, REQUEST):
def initZMS(self, id, titlealt, title, lang, manage_lang, REQUEST, minimal_init = False):

### Constructor.
obj = ZMS()
Expand Down Expand Up @@ -135,7 +135,7 @@ def initZMS(self, id, titlealt, title, lang, manage_lang, REQUEST):
obj.setConfProperty('ZMS.autocommit', 1)

### Init ZMS default content-model.
_confmanager.initConf(obj, 'conf:com.zms.foundation*')
_confmanager.initConf(obj, 'conf:com.zms.foundation' if minimal_init else 'conf:com.zms.foundation*')
_confmanager.initConf(obj, 'conf:com.zms.catalog.zcatalog')

### Init ZMS index.
Expand Down Expand Up @@ -374,13 +374,47 @@ def zms_version(self, custom=False):
file.close()
zms_custom_version = os.environ.get('ZMS_CUSTOM_VERSION', '')
if custom and zms_custom_version != '':
rtn += ' ({})'.format(zms_custom_version)
rtn += f'&nbsp;(<samp id="zms_custom_version">{zms_custom_version}</samp>)'
# Generate revisions and custom version gathering commit hashes of git submodules
# see Lines 37-46 unibe-cms/.github/workflows/build-and-push.yml
revisions = _fileutil.getOSPath('/app/revisions.txt')
if os.path.exists(revisions):
file = open(revisions, 'r')
zms_submodule_revisions = file.read()
file.close()
rtn += f"""
<span class="d-inline-block" data-toggle="popover"
title="Git revisions"
data-content="{zms_submodule_revisions}">
<i class="fab fa-git-square fa-lg"></i>
</span>
<script>
$(function () {{
$('[data-toggle="popover"]').popover();
// CAVEAT: Slicing below relies on commit hashes at https://github.com/idasm-unibe-ch/unibe-cms/tree/...
const zms_custom_version = $('#zms_custom_version').text().replaceAll('(', '').replaceAll(')', '');
const github_link = zms_custom_version.substr(zms_custom_version.indexOf('https://github.com'), zms_custom_version.length);
const version_str = zms_custom_version.substr(0, zms_custom_version.indexOf('https://github.com')).trim();
if (github_link.indexOf('https://github.com') == 0) {{
$('#zms_custom_version').html('<a href="'+github_link+'" title="'+github_link.slice(0, 58)+'" target="_blank">'+version_str+'</a>');
}}
}})
</script>
<style>
.popover-body {{
white-space: break-spaces;
width: auto;
font-size: smaller;
}}
</style>
"""
if custom and os.path.exists(_fileutil.getOSPath(package_home(globals())+'/../../.git/FETCH_HEAD')):
file = open(_fileutil.getOSPath(package_home(globals())+'/../../.git/FETCH_HEAD'),'r')
FETCH_HEAD = file.read()
file.close()
FETCH_HEAD = FETCH_HEAD[0:7]
rtn += ' git#%s'%(FETCH_HEAD)
rtn += (f'<a title="ZMS commits on github.com" target="_blank" '
f'href="https://github.com/zms-publishing/ZMS/commits/main"> git#{FETCH_HEAD}</a>')
return rtn

# --------------------------------------------------------------------------
Expand Down
30 changes: 13 additions & 17 deletions Products/zms/zmslog.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import logging
import os
import time
import glob
# Product Imports.
from Products.zms import standard
from Products.zms import ZMSItem
Expand Down Expand Up @@ -115,7 +114,7 @@ def LOG(self, severity, info):
# --------------------------------------------------------------------------
def getLOG(self, REQUEST, RESPONSE=None):
""" ZMSLog.getLOG """
filename = os.path.join(standard.getINSTANCE_HOME(),'var','log','event.log')
filename = self.get_log_filename()
RESPONSE.setHeader( 'Content-Type','text/plain')
RESPONSE.setHeader( 'Content-Disposition','inline;filename="%s"'%_fileutil.extractFilename( filename))
file = open( filename, 'r')
Expand All @@ -127,21 +126,18 @@ def getLOG(self, REQUEST, RESPONSE=None):
# ZMSLog.tail_event_log:
# --------------------------------------------------------------------------
def tail_event_log(self, linesback=100, returnlist=True):
filename = os.path.join(standard.getINSTANCE_HOME(),'var','log','event.log')
try:
return _fileutil.tail_lines(filename,linesback,returnlist)
except:
filename_prefix = os.path.join(standard.getINSTANCE_HOME(),'var','log','event')
filename_list = [f for f in glob.glob( r'' + filename_prefix + r'*.log')]
error_info = ['ERROR:']
error_info.append('Default event log file %s not found.'%(filename))
error_info.append('Please check zope.ini [handler_eventlog]')
if filename_list:
error_info.append('')
error_info.append('Following event log files are found:')
error_info.extend(filename_list)
error_info.append('HINT: If one of them is sym-linked as event.log, it will be showm.')
return error_info
filename = self.get_log_filename()
return _fileutil.tail_lines(filename,linesback,returnlist)

# --------------------------------------------------------------------------
# ZMSLog.get_log_filename:
# --------------------------------------------------------------------------
def get_log_filename():
logging_file_handlers = [x for x in logging.root.handlers if isinstance(x, logging.FileHandler)]
if len(logging_file_handlers) == 0:
raise RuntimeError('No event log file handler defined in zope.ini ([handler_eventlog])')
return logging_file_handlers[0].baseFilename




Expand Down
19 changes: 0 additions & 19 deletions Products/zms/zmsobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,25 +138,6 @@ def getPath(self, *args, **kwargs):
ids = [ids[x] for x in range(len(ids)) if x == 0 or not ids[x-1] == ids[x]]
return '/'.join(ids)

"""
Check if feature toggle is set.
@rtype: C{boolean}
"""
def isFeatureEnabled(self, feature=''):

# get conf from current client
confprop = self.breadcrumbs_obj_path(False)[0].getConfProperty('ZMS.Features.enabled', '')
features = confprop.replace(',', ';').split(';')
# get conf from top master if there is no feature toggle set at client
if len(features)==1 and features[0].strip()=='':
confprop = self.breadcrumbs_obj_path(True)[0].getConfProperty('ZMS.Features.enabled', '')
features = confprop.replace(',', ';').split(';')

if len([x for x in features if x.strip()==feature.strip()])>0:
return True
else:
return False


# --------------------------------------------------------------------------
# ZMSObject.f_css_defaults:
Expand Down
8 changes: 2 additions & 6 deletions Products/zms/zpt/ZMS/manage_customize.zpt
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,7 @@
<div class="form-group row">
<label class="col-sm-2 control-label">ZMS Version</label>
<div class="col-sm-10">
<a title="ZMS commits on github.com" target="_blank"
href="https://github.com/zms-publishing/ZMS/commits/main">
<samp id="zms_custom_version" tal:content="structure python:here.zms_version(custom=True)">zms_version</samp>
</a>
<samp tal:content="structure python:here.zms_version(custom=True)">zms_version</samp>
</div>
</div><!-- .form-group -->
<div class="form-group row">
Expand All @@ -363,10 +360,9 @@
<label class="col-sm-2 control-label" for="installed_python_packages">
Installed Python Packages
<p class="help-text small mt-sm-3 mb-0">
Tools such as the <a href="https://pip.pypa.io/en/stable/reference/pip/" target="_blank">Python Package Installer</a>
Tools such as the <a href="https://pip.pypa.io/en/stable/cli/pip/" target="_blank">Python Package Installer</a>
with <a href="https://pip.pypa.io/en/stable/user_guide/#requirements-files" target="_blank">requirements</a>
and <a href="https://pip.pypa.io/en/stable/user_guide/#constraints-files" target="_blank">constraints</a> files
and <a href="https://requires.io/github/zopefoundation/Zope/requirements/?branch=master" target="_blank">requires.io</a>
help manage and monitor package dependencies.
</p>
</label>
Expand Down
8 changes: 5 additions & 3 deletions Products/zms/zpt/common/zmi_breadcrumbs_obj_path.zpt
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
tal:attributes="onclick python:'javascript:window.open(\'%s/%s\',\'MetaObjectManagerWindow\')'%(zmscontext.getDocumentElement().getAbsoluteUrlInContext(here),middot)"
><tal:block tal:condition="python:childNode==childNodes[-1]"
tal:on-error="nothing"
><i class="far fa-file-alt" title="Icon" tal:attributes="class python:childNode.zmi_icon();title python:childNode.meta_id"></i
><i class="far fa-file-alt" title="Icon" tal:attributes="class python:childNode.attr('attr_dc_identifier_url_redirect')=='' and childNode.zmi_icon();title python:childNode.meta_id"></i
></tal:block
></span>&nbsp;<a tal:define="
></span><i class="far fa-share-square" title="Icon" tal:condition="python:childNode.attr('attr_dc_identifier_url_redirect')!=''"></i>&nbsp;
<a tal:define="
titlealt python:childNode.getTitlealt(request);
title python:childNode.getTitle(request);
visible python:childNode.isVisible(request) and 'text-decoration:normal;;' or 'text-decoration:line-through;;';
accesskey repeat/childNode/number;"
tal:attributes="href python:'%s/manage_main?lang=%s'%(childNode.getAbsoluteUrlInContext(here),request['lang']);title title;accesskey accesskey"
tal:attributes="href python:'%s/manage_main?lang=%s'%(childNode.getAbsoluteUrlInContext(here),request['lang']);title title;accesskey accesskey;style visible;"
tal:content="structure titlealt">titlealt
</a></li>
<li class="breadcrumb-item" tal:repeat="extra python:options.get('extra',[])">
Expand Down

0 comments on commit b9d72c5

Please sign in to comment.