From 60ca4c55728ee9472e4f3f9ec4110cc6141b4e2e Mon Sep 17 00:00:00 2001
From: Yoshinori Okuji <yo@nexedi.com>
Date: Tue, 17 Aug 2004 14:23:50 +0000
Subject: [PATCH] Initial import.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@1379 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5/Extensions/CheckSkins.py | 341 ++++++++++++++++++++++++++
 1 file changed, 341 insertions(+)
 create mode 100755 product/ERP5/Extensions/CheckSkins.py

diff --git a/product/ERP5/Extensions/CheckSkins.py b/product/ERP5/Extensions/CheckSkins.py
new file mode 100755
index 0000000000..6259fe2010
--- /dev/null
+++ b/product/ERP5/Extensions/CheckSkins.py
@@ -0,0 +1,341 @@
+from Globals import get_request
+import re
+import os
+import sys
+
+try:
+    from App.config import getConfiguration
+except ImportError:
+    getConfiguration = None
+
+if getConfiguration is None:
+  data_dir = '/var/lib/zope/data'
+else:
+  data_dir = getConfiguration().instancehome + '/data'
+
+fs_skin_spec = ('ERP5 Filesystem Formulator Form',
+                'ERP5 Filesystem PDF Template',
+                'Filesystem Formulator Form',
+                'Filesystem Page Template',
+                'Filesystem Script (Python)',
+                'Filesystem Z SQL Method')
+
+zodb_skin_spec = ('ERP5 Form', 'ERP5 PDF Template', 'Page Template', 'Script', 'Script (Python)','Z SQL Method')
+
+def getSkinPathList(self, spec=fs_skin_spec+zodb_skin_spec):
+  path_list = self.portal_skins.getSkinPath(self.portal_skins.getDefaultSkin())
+  path_list = path_list.split(',')
+  skin_list = []
+  for path in path_list:
+    if path in ('content', 'content18', 'control', 'generic', 'mailin', 'pro', 'topic', 'zpt_content', 'zpt_control', 'zpt_generic', 'zpt_reporttool', 'zpt_topic'):
+      continue
+    for id in self.portal_skins[path].objectIds(spec):
+      skin_list.append(path + '/' + id)
+  return skin_list
+
+def split(name):
+  """
+    Split the name using an underscore as a separator and
+    using the change from lower case to upper case as a separator.
+
+    Example: foo_barBaz -> foo, bar, Baz
+  """
+  part_list = []
+  part = ''
+  pc = None
+  for c in name:
+    if c == '_':
+      if len(part) > 0:
+        part_list.append(part)
+      part = ''
+      pc = None
+    elif pc is not None and pc.islower() and c.isupper():
+      if len(part) > 0:
+        part_list.append(part)
+      part = c
+      pc = None
+    else:
+      pc = c
+      part += c
+  if pc is not None:
+    part_list.append(part)
+  return part_list
+
+def suggestName(name, meta_type):
+  """
+    Suggest a good name for a given name.
+  """
+  # Determine the prefix. The default is "Base_".
+  i = name.find('_')
+  if i < 1:
+    prefix = 'Base'
+  else:
+    # Special treatment for view, print, create and list, because they are used very often.
+    # packing list is an exception, because it is confusing (i.e. sale_packing_list_list).
+    view_index = name.find('_view')
+    print_index = name.find('_print')
+    create_index = name.find('_create')
+    list_index = name.find('_list')
+    packing_list_index = name.find('packing_list_')
+    if view_index > 0:
+      i = view_index
+    elif print_index > 0:
+      i = print_index
+    elif create_index > 0:
+      i = create_index
+    elif list_index > 0:
+      if packing_list_index > 0:
+        i = packing_list_index + 12
+      else:
+        i = list_index
+    part_list = split(name[:i])
+    prefix = ''
+    for part in part_list:
+      prefix += part.capitalize()
+    name = name[i+1:]
+  if meta_type in ('Filesystem Z SQL Method', 'Z SQL Method'):
+    new_name = 'z'
+    if name[0] == 'z':
+      name = name[1:]
+    part_list = split(name)
+    for part in part_list:
+      new_name += part.capitalize()
+  else:
+    part_list = split(name)
+    new_name = part_list[0].lower()
+    for part in part_list[1:]:
+      new_name += part.capitalize()
+  return prefix + '_' + new_name
+
+
+def checkSkinNames(self, REQUEST=None, csv=0, all=0):
+  """
+    Check if the name of each skin follows the naming convention.
+  """
+  if csv:
+    msg = 'Folder,Name,New Name,Meta Type\n'
+  else:
+    msg = '<html><body>'
+  rexp = re.compile('^[A-Z][a-zA-Z0-9]*_[a-z][a-zA-Z0-9]*$')
+  rexp_zsql = re.compile('^[A-Z][a-zA-Z0-9]*_z[A-Z][a-zA-Z0-9]*$')
+  path_list = getSkinPathList(self)
+  bad_list = []
+  for path in path_list:
+    name = path.split('/')[-1]
+    skin = self.portal_skins.restrictedTraverse(path)
+    if skin.meta_type in ('Filesystem Z SQL Method', 'Z SQL Method'):
+      r = rexp_zsql
+    else:
+      r = rexp
+    if all or r.search(name) is None:
+      bad_list.append((path, skin.meta_type))
+  if len(bad_list) == 0:
+    if not csv:
+      msg += '<p>Everything is fine.</p>\n'
+  else:
+    bad_list.sort()
+    if not csv:
+      msg += '<p>These %d skins do not follow the naming convention:</p><table width="100%%">\n' % len(bad_list)
+      msg += '<tr><td>Folder</td><td>Skin Name</td><td>Meta Type</td></tr>\n'
+    i = 0
+    for path,meta_type in bad_list:
+      name = path.split('/')[-1]
+      suggested_name = suggestName(name, meta_type)
+      folder = path[:-len(name)-1]
+      if (i % 2) == 0:
+        c = '#88dddd'
+      else:
+        c = '#dddd88'
+      i += 1
+      if csv:
+        msg += '%s,%s,%s,%s\n' % (folder, name, suggested_name, meta_type)
+      else:
+        msg += '<tr bgcolor="%s"><td>%s</td><td>%s</td><td>%s</td></tr>\n' % (c, folder, name, meta_type)
+    if not csv:
+      msg += '</table>\n'
+  if not csv:
+    msg += '</body></html>'
+  return msg
+
+def fixSkinNames(self, REQUEST=None, file=None, dry_run=1):
+  """
+    Fix bad skin names.
+
+    This method does:
+
+      - Check all the contents of all skins.
+
+      - Check immediate_view, constructor_path and actions in all portal types.
+
+      - Check skins of all business templates.
+
+      - Check actbox_url in transitions and worklists and scripts of all workflows.
+
+      - Rename skins.
+  """
+  if REQUEST is None:
+    REQUEST = get_request()
+
+  if file is None:
+    msg = 'You must put a CSV file inside the data directory, and specify %s/ERP5Site_fixSkinNames?file=NAME \n\n' % self.absolute_url()
+    msg += 'The template of a CSV file is available via %s/ERP5Site_checkSkinNames?csv=1 \n\n' % self.absolute_url()
+    msg += 'This does not modify anything by default. If you really want to fix skin names, specify %s/ERP5Site_fixSkinNames?file=NAME&dry_run=0 \n\n' % self.absolute_url()
+    return msg
+
+  file = os.path.join(data_dir, file)
+  file = open(file, 'r')
+  class NamingInformation: pass
+  info_list = []
+  try:
+    for line in file:
+      folder, name, new_name, meta_type = line.strip().split(',')
+      if meta_type == 'Meta Type': continue
+      if name == new_name: continue
+      # Check the existence of the skin and the meta type. Paranoid?
+      #if self.portal_skins[folder][name].meta_type != meta_type:
+      #  raise RuntimeError, '%s/%s has a different meta type' % (folder, name)
+      info = NamingInformation()
+      info.folder = folder
+      info.name = name
+      info.new_name = new_name
+      info.regexp = re.compile('\\b' + re.escape(name) + '\\b') # This is used to search the name
+      info_list.append(info)
+  finally:
+    file.close()
+
+  # Now we have information enough. Check the skins.
+  msg = ''
+  path_list = getSkinPathList(self)
+  for path in path_list:
+    skin = self.portal_skins.restrictedTraverse(path)
+    try:
+      text = skin.manage_FTPget()
+    except:
+      type, value, traceback = sys.exc_info()
+      msg += 'WARNING: the skin %s could not be retrieved because of the exception %s: %s\n' % (path, str(type), str(value))
+    else:
+      name_list = []
+      for info in info_list:
+        if info.regexp.search(text) is not None:
+          text = info.regexp.sub(info.new_name, text)
+          name_list.append(info.name)
+      if len(name_list) > 0:
+        msg += '%s is modified for %s\n' % ('portal_skins/' + path, ', '.join(name_list))
+        if not dry_run:
+          REQUEST['BODY'] = text
+          skin.manage_FTPput(REQUEST, REQUEST.RESPONSE)
+
+  # Check the portal types.
+  for t in self.portal_types.objectValues():
+    # Initial view name.
+    text = t.immediate_view
+    for info in info_list:
+      if info.name == text:
+        msg += 'Initial view name of %s is modified for %s\n' % ('portal_types/' + t.id, text)
+        if not dry_run:
+          t.immediate_view = info.new_name
+        break
+    # Constructor path.
+    text = getattr(t, 'constructor_path', None)
+    if text is not None:
+      for info in info_list:
+        if info.name == text:
+          msg += 'Constructor path of %s is modified for %s\n' % ('portal_types/' + t.id, text)
+          if not dry_run:
+            t.constructor_path = info.new_name
+          break
+    # Actions.
+    for action in t.listActions():
+      text = action.action.text
+      for info in info_list:
+        if info.regexp.search(text) is not None:
+          text = info.regexp.sub(info.new_name, text)
+          msg += 'Action %s of %s is modified for %s\n' % (action.getId(), 'portal_types/' + t.id, info.name)
+          if not dry_run:
+            action.action.text = text
+          break
+
+  # Check the portal templates.
+  template_tool = getattr(self, 'portal_templates', None)
+  # Check the existence of template tool, because an older version of ERP5 does not have it.
+  if template_tool is not None:
+    for template in template_tool.contentValues(filter={'portal_type':'Business Template'}):
+      # Skins.
+      skin_id_list = []
+      name_list = []
+      for skin_id in template.getTemplateSkinIdList():
+        for info in info_list:
+          if info.name == skin_id:
+            name_list.append(skin_id)
+            skin_id = info.new_name
+            break
+        skin_id_list.append(skin_id)
+      if len(name_list) > 0:
+        msg += 'Skins of %s is modified for %s\n' % ('portal_templates/' + template.getId(), ', '.join(name_list))
+        if not dry_run:
+          template.setTemplateSkinIdList(skin_id_list)
+      # Paths.
+      path_list = []
+      name_list = []
+      for path in template.getTemplatePathList():
+        for info in info_list:
+          if info.regexp.search(path):
+            name_list.append(skin_id)
+            path = info.regexp.sub(info.new_name, path)
+            break
+        path_list.append(path)
+      if len(name_list) > 0:
+        msg += 'Paths of %s is modified for %s\n' % ('portal_templates/' + template.getId(), ', '.join(name_list))
+        if not dry_run:
+          template.setTemplatePathList(path_list)
+
+  # Workflows.
+  for wf in self.portal_workflow.objectValues():
+    # Transitions.
+    for id in wf.transitions.objectIds():
+      transition = wf.transitions._getOb(id)
+      text = transition.actbox_url
+      for info in info_list:
+        if info.regexp.search(text) is not None:
+          text = info.regexp.sub(info.new_name, text)
+          msg += 'Transition %s of %s is modified for %s\n' % (id, 'portal_workflow/' + wf.id, info.name)
+          if not dry_run:
+            transition.actbox_url = text
+          break
+    # Worklists.
+    for id in wf.worklists.objectIds():
+      worklist = wf.worklists._getOb(id)
+      text = worklist.actbox_url
+      for info in info_list:
+        if info.regexp.search(text) is not None:
+          text = info.regexp.sub(info.new_name, text)
+          msg += 'Worklist %s of %s is modified for %s\n' % (id, 'portal_workflow/' + wf.id, info.name)
+          if not dry_run:
+            worklist.actbox_url = text
+          break
+    # Scripts.
+    for id in wf.scripts.objectIds():
+      script = wf.scripts._getOb(id)
+      text = script.manage_FTPget()
+      name_list = []
+      for info in info_list:
+        if info.regexp.search(text) is not None:
+          text = info.regexp.sub(info.new_name, text)
+          name_list.append(info.name)
+      if len(name_list) > 0:
+        msg += 'Script %s of %s is modified for %s\n' % (id, 'portal_workflow/' + wf.id, ', '.join(name_list))
+        if not dry_run:
+          REQUEST['BODY'] = text
+          script.manage_FTPput(REQUEST, REQUEST.RESPONSE)
+
+  # Rename the skins.
+  if not dry_run:
+    for info in info_list:
+      try:
+        folder = self.portal_skins[info.folder]
+        folder.manage_renameObjects([info.name], [info.new_name])
+      except:
+        type, value, traceback = sys.exc_info()
+        msg += 'WARNING: the skin %s could not be renamed to %s because of the exception %s: %s\n' % (info.name, info.new_name, str(type), str(value))
+
+  return msg
\ No newline at end of file
-- 
2.30.9