From bd3d074957ad40dc4fb31127e269e53ac0e8fd46 Mon Sep 17 00:00:00 2001
From: Vincent Pelletier <vincent@nexedi.com>
Date: Fri, 29 Dec 2006 13:35:32 +0000
Subject: [PATCH] Add custom catalog storage support at site creation. Add
 custom catalog storage selection in unit test system.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@11797 20353a03-c40f-0410-a6d1-a30d3c3de9de
---
 product/ERP5/ERP5Site.py                   | 76 +++++++++++++++++-----
 product/ERP5/dtml/addERP5Site.dtml         | 19 +++++-
 product/ERP5Type/tests/ERP5TypeTestCase.py |  8 ++-
 product/ERP5Type/tests/runUnitTest.py      | 11 +++-
 4 files changed, 93 insertions(+), 21 deletions(-)

diff --git a/product/ERP5/ERP5Site.py b/product/ERP5/ERP5Site.py
index 9c21253def..7f9fe2a1d9 100644
--- a/product/ERP5/ERP5Site.py
+++ b/product/ERP5/ERP5Site.py
@@ -40,7 +40,15 @@ MARKER = []
 
 
 # Site Creation DTML
-manage_addERP5SiteForm = Globals.HTMLFile('dtml/addERP5Site', globals())
+manage_addERP5SiteFormDtml = Globals.HTMLFile('dtml/addERP5Site', globals())
+
+def manage_addERP5SiteForm(*args, **kw):
+  """
+    Make getCatalogStorageList available from inside the dtml.
+  """
+  kw['getCatalogStorageList'] = getCatalogStorageList
+  return manage_addERP5SiteFormDtml(*args, **kw)
+
 manage_addERP5SiteForm.__name__ = 'addERP5Site'
 
 # ERP5Site Constructor
@@ -53,6 +61,7 @@ def manage_addERP5Site(self,
                        email_from_address='postmaster@localhost',
                        email_from_name='Portal Administrator',
                        validate_email=0,
+                       erp5_catalog_storage='',
                        erp5_sql_connection_type='Z MySQL Database Connection',
                        erp5_sql_connection_string='test test',
                        erp5_sql_deferred_connection_type = \
@@ -72,6 +81,7 @@ def manage_addERP5Site(self,
   p = gen.create(self,
                  id,
                  create_userfolder,
+                 erp5_catalog_storage,
                  erp5_sql_connection_type,
                  erp5_sql_connection_string,
                  erp5_sql_deferred_connection_type,
@@ -90,6 +100,40 @@ def manage_addERP5Site(self,
   if RESPONSE is not None:
     RESPONSE.redirect(p.absolute_url())
 
+def getCatalogStorageList(*args, **kw):
+  """
+    Returns the list of business templates available at install which can be
+    used to setup a catalog storage.
+  """
+  result = []
+  bootstrap_dir = getBootstrapDirectory()
+  #import pdb; pdb.set_trace()
+  for item in os.listdir(bootstrap_dir):
+    #LOG('getCatalogStorageList', 0, item)
+    if item == '.svn':
+      continue
+    if item.endswith('.bt5') and os.path.isfile():
+      # Simple heuristic to make it faster than extracting the whole bt
+      if item.endswith('_catalog.bt5'):
+        result.append((item, item))
+    elif os.path.isdir(os.path.join(bootstrap_dir, item)):
+      # Find if the business temlate provides erp5_catalog
+      try:
+        provides_file = open(os.path.join(bootstrap_dir, item, 'bt', 'provision_list'), 'r')
+        provides_list = provides_file.readlines()
+        provides_file.close()
+      except IOError:
+        provides_list = []
+      if 'erp5_catalog' in provides_list:
+        # Get a nice title (the first line of the description).
+        try:
+          title_file = open(os.path.join(bootstrap_dir, item, 'bt', 'description'), 'r')
+          title = title_file.readline()
+          title_file.close()
+        except IOError:
+          title = item
+        result.append((item, title))
+  return result
 
 class ReferCheckerBeforeTraverseHook:
   """This before traverse hook checks the HTTP_REFERER argument in the request
@@ -891,21 +935,25 @@ class ERP5Site(FolderMixIn, CMFSite):
 
 Globals.InitializeClass(ERP5Site)
 
+def getBootstrapDirectory():
+  """
+    Return the name of the bootstrap directory
+  """
+  product_path = package_home(globals())
+  return os.path.join(product_path, 'bootstrap')
+
 class ERP5Generator(PortalGenerator):
 
   klass = ERP5Site
 
   def getBootstrapDirectory(self):
-    """
-      Return the name of the bootstrap directory
-    """
-    product_path = package_home(globals())
-    return os.path.join(product_path, 'bootstrap')
+    return getBootstrapDirectory()
 
   def create(self,
              parent,
              id,
              create_userfolder,
+             erp5_catalog_storage,
              erp5_sql_connection_type,
              erp5_sql_connection_string,
              erp5_sql_deferred_connection_type,
@@ -923,6 +971,8 @@ class ERP5Generator(PortalGenerator):
     parent._setObject(id, portal)
     # Return the fully wrapped object.
     p = parent.this()._getOb(id)
+    p._setProperty('erp5_catalog_storage',
+                   erp5_catalog_storage, 'string')
     p._setProperty('erp5_sql_connection_type',
                    erp5_sql_connection_type, 'string')
     p._setProperty('erp5_sql_connection_string',
@@ -1092,14 +1142,6 @@ class ERP5Generator(PortalGenerator):
     elif p.cmf_activity_sql_connection_type == 'Z Gadfly':
       pass
 
-    portal_catalog = getToolByName(p, 'portal_catalog')
-    if (not update) and (not portal_catalog.getSQLCatalog('erp5_mysql')):
-      # Add a empty SQL Catalog, which will be filled when installing
-      # erp5_core business template
-      portal_catalog.manage_addProduct['ZSQLCatalog'].manage_addSQLCatalog(
-          'erp5_mysql', 'ERP5/MySQL')
-      portal_catalog.default_sql_catalog_id = 'erp5_mysql'
-
     # Add ERP5Form Tools
     addTool = p.manage_addProduct['ERP5Form'].manage_addTool
     if not p.hasObject('portal_selections'):
@@ -1369,7 +1411,11 @@ class ERP5Generator(PortalGenerator):
       return
     if template_tool.getInstalledBusinessTemplate('erp5_core') is None:
       bootstrap_dir = self.getBootstrapDirectory()
-      for bt in ('erp5_core', 'erp5_xhtml_style'):
+      if p.erp5_catalog_storage is not '':
+        business_template_list = ('erp5_core', p.erp5_catalog_storage, 'erp5_xhtml_style')
+      else:
+        business_template_list = ('erp5_core', 'erp5_xhtml_style')
+      for bt in business_template_list:
         template = os.path.join(bootstrap_dir, bt)
         if not os.path.exists(template):
           template = os.path.join(bootstrap_dir, '%s.bt5' % bt)
diff --git a/product/ERP5/dtml/addERP5Site.dtml b/product/ERP5/dtml/addERP5Site.dtml
index 2caa047249..5a9760a51d 100644
--- a/product/ERP5/dtml/addERP5Site.dtml
+++ b/product/ERP5/dtml/addERP5Site.dtml
@@ -75,6 +75,20 @@ label {
 
   <fieldset>
     <legend class="form-title">ERP5/MySQL connectivity (connection strings)</legend>
+    <div>
+      <label class="form-label" for="erp5_catalog_storage">Catalog storage</label>
+      <select class="form-element" name="erp5_catalog_storage" id="erp5_catalog_storage" size="1">
+        <dtml-in "getCatalogStorageList()">
+          <dtml-let btid=sequence-key>
+            <dtml-if expr="btid == 'erp5_mysql_innodb_catalog'">
+              <option value="<dtml-var sequence-key html_quote>" selected="selected"><dtml-var sequence-item html_quote></option>
+            <dtml-else>
+              <option value="<dtml-var sequence-key html_quote>"><dtml-var sequence-item html_quote></option>
+            </dtml-if>
+          </dtml-let>
+        </dtml-in>
+      </select>
+    </div>
     <div>
       <label class="form-label" for="erp5_sql_connection_string">ERP5 Database</label>
       <input class="form-element" name="erp5_sql_connection_string" id="erp5_sql_connection_string" type="text" size="40" value="test test"/>
@@ -88,7 +102,7 @@ label {
       <input class="form-element" name="cmf_activity_sql_connection_string" id="cmf_activity_sql_connection_string" type="text" size="40" value="test test"/>
     </div>
     <div>
-      <p>The connection string used for Z MySQL Database Connection are of the form:</p>
+      <p>The connection strings used for Z MySQL Database Connections are of the form:</p>
       <blockquote><code>database[@host[:port]] [user [password [unix_socket]]]</code></blockquote>
     </div>
     <br/>
@@ -103,4 +117,5 @@ label {
   <dtml-var manage_page_footer>
 <dtml-else>
   </body></html>
-</dtml-if>
\ No newline at end of file
+</dtml-if>
+
diff --git a/product/ERP5Type/tests/ERP5TypeTestCase.py b/product/ERP5Type/tests/ERP5TypeTestCase.py
index 58036b9294..0afe19a2e6 100644
--- a/product/ERP5Type/tests/ERP5TypeTestCase.py
+++ b/product/ERP5Type/tests/ERP5TypeTestCase.py
@@ -297,13 +297,15 @@ class ERP5TypeTestCase(PortalTestCase):
       light_install = self.enableLightInstall()
       create_activities = self.enableActivityTool()
       hot_reindexing = self.enableHotReindexing()
+      erp5_catalog_storage = os.environ.get('erp5_catalog_storage', 'erp5_mysql_innodb_catalog')
       setupERP5Site(business_template_list=new_template_list,
                     light_install=light_install,
                     portal_name=self.getPortalName(),
                     title=self.getTitle(),
                     create_activities=create_activities,
                     quiet=install_bt5_quiet,
-                    hot_reindexing=hot_reindexing)
+                    hot_reindexing=hot_reindexing,
+                    erp5_catalog_storage=erp5_catalog_storage)
       PortalTestCase.setUp(self)
       global current_app
       current_app = self.app
@@ -460,7 +462,8 @@ def setupERP5Site( business_template_list=(),
                    quiet=0,
                    light_install=1,
                    create_activities=1,
-                   hot_reindexing=1 ):
+                   hot_reindexing=1,
+                   erp5_catalog_storage='erp5_mysql_innodb_catalog'):
     '''
       Creates an ERP5 site.
       business_template_list must be specified correctly
@@ -500,6 +503,7 @@ def setupERP5Site( business_template_list=(),
             extra_constructor_kw['email_from_address'] = email_from_address
           factory = app.manage_addProduct['ERP5']
           factory.manage_addERP5Site(portal_name,
+                                     erp5_catalog_storage=erp5_catalog_storage,
                                      light_install=light_install,
                                      reindex=reindex,
                                      create_activities=create_activities,
diff --git a/product/ERP5Type/tests/runUnitTest.py b/product/ERP5Type/tests/runUnitTest.py
index 3103eacece..b10bbc39e0 100755
--- a/product/ERP5Type/tests/runUnitTest.py
+++ b/product/ERP5Type/tests/runUnitTest.py
@@ -35,7 +35,11 @@ Options:
                              Initialize the email_from_address property of the
                              portal, by defaults, CMFActivity failures are sent
                              on localhost from this address, to this address
- 
+  --erp5_catalog_storage=STRING
+                             Use the given business template as erp5_catalog
+                             dependency provider (ie, the name of the BT
+                             containing ZSQLMethods matching the desired
+                             catalog storage).
 """
 
 def getUnitTestFile():
@@ -190,7 +194,8 @@ def main():
         "hpv", ["help", "verbose", "profile", "portal_id=", "data_fs_path=",
         "recreate_catalog=", "erp5_sql_connection_string=",
         "cmf_activity_sql_connection_string=",
-        "erp5_deferred_sql_connection_string=",
+        "erp5_sql_deferred_connection_string=",
+        "erp5_catalog_storage=",
         "email_from_address="] )
   except getopt.GetoptError, msg:
     usage(sys.stderr, msg)
@@ -227,6 +232,8 @@ def main():
       os.environ["erp5_sql_deferred_connection_string"] = arg
     elif opt == "--email_from_address":
       os.environ["email_from_address"] = arg
+    elif opt == "--erp5_catalog_storage":
+      os.environ["erp5_catalog_storage"] = arg
 
   test_list = args
   if not test_list:
-- 
2.30.9