Changeset 935

Show
Ignore:
Timestamp:
08/15/07 11:41:27
Author:
mylan
Message:

Add portlet dumping possibility. Perform installation using portal_setup.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • qPloneSkinDump/branches/plone_3.0/config.py

    r932 r935  
    2727DEFAULT_IMPORTING_POLICY = "only_new" 
    2828FORBIDDEN_EXP_PREFIXES = re.compile('^(portal_)') 
    29 FORBIDDEN_EXP_NAMES = ["MailHost", "HTTPCache", "Members", "RAMCache", "acl_users",\ 
     29FORBIDDEN_EXP_NAMES = ["ResourceRegistryCache", "MailHost", "HTTPCache", "Members", "RAMCache", "acl_users",\ 
    3030                       "archetype_tool", "caching_policy_manager", "content_type_registry", \ 
    3131                       "cookie_authentication", "error_log", "kupu_library_tool",\ 
  • qPloneSkinDump/branches/plone_3.0/qPloneSkinDump.py

    r894 r935  
    6464                  exporting_objects=[], \ 
    6565                  dump_CSS=True, \ 
    66                   dump_JS=True ): 
     66                  dump_JS=True, \ 
     67                  dump_portlets=0, \ 
     68                  dump_policy='root', \ 
     69                  dump_portlets_selection=[]): 
    6770    """ Main Skin Product creating procedure.""" 
    6871    makeNewProduct(context, fs_product_name, fs_skin_directory, \ 
     
    7073                   doesCustomizeSlots, left_slots, right_slots, slot_forming, main_column, \ 
    7174                   doesExportObjects, import_policy, \ 
    72                    dump_CSS, dump_JS
     75                   dump_CSS, dump_JS, dump_portlets, dump_policy, dump_portlets_selection
    7376    dumpSkin(context, zmi_skin_name, subdir, fs_skin_directory.lower(), 
    7477             fs_product_name, erase_from_skin) 
  • qPloneSkinDump/branches/plone_3.0/skin_template/Extensions/Install.py

    r503 r935  
    1 import string 
    2 from StringIO import StringIO 
    3 from zLOG import LOG, INFO 
     1import transaction 
    42from Products.CMFCore.utils import getToolByName 
    5 from Products.%(SKIN_PRODUCT_NAME)s.config import * 
    6 from Products.%(SKIN_PRODUCT_NAME)s.Extensions.utils import * 
    73 
    8 CHECKED_MESSAGE = "The base installation checkings completed." 
     4EXTENSION_PROFILES = ('Products.%(product_name)s:default',) 
    95 
    10 def prepareInstallation(portal, pp, product, out): 
    11     checkSuccessInstall(product) 
    12     uninstallOtherSkinProducts(portal) 
    13     if not ('uninstall_properties' in pp.objectIds()) : 
    14         pp.addPropertySheet(id='uninstall_properties', title= 'uninstall_properties') 
    15         print >> out, "Created 'portal_properties.uninstall_properties' PropertySheet (UP) for backup purpose" 
     6def install(self, reinstall=False): 
    167 
    17 def checkSuccessInstall(product): 
    18     # Check for successfully completed 1 installation step 
    19     transcript = getattr(product,'transcript',None) 
    20     if transcript: 
    21         msg = str(transcript[0]['msg']) 
    22         if msg.find(CHECKED_MESSAGE) < 0 : 
    23             product.log("First part installation procedure not completed - installation terminated.") 
    24             raise 
     8    portal_setup = getToolByName(self, 'portal_setup') 
    259 
    26 def uninstallOtherSkinProducts(portal): 
    27     qi=getToolByName(portal, 'portal_quickinstaller', None) 
    28     if not qi: 
    29         raise Exception("Can't work without QuickInstaller tool.") 
    30     # Get installed products 
    31     installed_products = [getattr(qi, p_dict['id']) \ 
    32                           for p_dict in qi.listInstalledProducts() 
    33                           if p_dict['id'] != PRODUCT_NAME] 
    34     seek_str = "%%s generated product" %% GENERATOR_PRODUCT 
    35     installed_skin_products = [] 
    36     # Looking for installed skin-products 
    37     for p in installed_products: 
    38         transcript = p.getTranscriptAsText() 
    39         if transcript.find(seek_str) >= 0 : 
    40             installed_skin_products.append(p.getId()) 
    41     # Uninstall found skin-products 
    42     if installed_skin_products: 
    43         qi.uninstallProducts(products=installed_skin_products) 
    44  
    45 def install(self): 
    46     # Checking base condition for installation 
    47     skinsTool = getToolByName(self, 'portal_skins') 
    48     # Checking for BASE_SKIN_NAME presenting in portal 
    49     skin_names = skinsTool.getSkinSelections() 
    50     if not BASE_SKIN_NAME in skin_names: 
    51         raise AttributeError("Impossible installation without %%s skin." %% BASE_SKIN_NAME) 
    52     # Checking for presenting lower_SKIN_NAME directory in portal skins 
    53     lower_SKIN_NAME = string.lower(SKIN_NAME) 
    54     if lower_SKIN_NAME in skinsTool.objectIds(): 
    55         raise AttributeError("%%s skin layer already exist in portal skins. Installation Impossible." %% lower_SKIN_NAME) 
    56     return CHECKED_MESSAGE 
    57  
    58 # For prevent quickInstaller's intervention in uninstall process - use afterInstall 
    59 def afterInstall(self,product,reinstall): 
    60     out=StringIO() 
    61     # get all needed tools and some portal's core objects 
    62     portal = getToolByName(self, 'portal_url').getPortalObject() 
    63     pp = getToolByName(portal, 'portal_properties') 
    64     portal_css = getToolByName(portal, 'portal_css', None) 
    65     portal_js = getToolByName(portal, 'portal_javascripts', None) 
    66     # Make main prepare procedures 
    67     prepareInstallation(portal, pp, product, out) 
    68     pp_up = pp.uninstall_properties 
    69     # Install skin 
    70     installSkin(portal, pp_up, out) 
    71     # Register css resources 
    72     if portal_css and DOES_COSTOMIZE_CSS: 
    73         registerResource(pp_up, portal_css, portal_css.registerStylesheet, out \ 
    74                         ,CSS_LIST, SKIN_CSS_REGDATA, 'q_registered_css', CSS_REG_PROPS) 
    75         print >> out, "Completed tuning CSS registry for new skin needs." 
    76     # Register js resources 
    77     if portal_js and DOES_COSTOMIZE_JS: 
    78         registerResource(pp_up, portal_js, portal_js.registerScript, out \ 
    79                         ,JS_LIST, SKIN_JS_REGDATA, 'q_registered_js', JS_REG_PROPS)#---installJS--- 
    80         print >> out, "Completed tuning JS registry for new skin needs." 
    81     # Customize slots     
    82     if LEFT_SLOTS or RIGHT_SLOTS: 
    83         customizeSlots(portal, pp_up, out) 
    84     # Import object(s) to portal 
    85     if checkIfImport(): 
    86         res_import = performImportToPortal(portal) 
    87         print >> out, res_import 
    88     # FINAL customization call additional functions from config  
    89     if FINAL_CUSTOMIZATION_FUNCTIONS: 
    90         dummy = [func(portal, out) for func in FINAL_CUSTOMIZATION_FUNCTIONS] 
    91     print >> out, "%%s generated product." %% GENERATOR_PRODUCT 
    92     print >> out, '=== Installation successfully completed. ===' 
    93     product.log(out.getvalue()) 
    94     product._p_changed = 1 #XXX:NEED for stable writing 'out' log to qi on afterinstallation. 
    95     return out.getvalue() 
    96  
    97 def uninstall(self): 
    98     # get all needed tools and some portal's core objects 
    99     portal = self.portal_url.getPortalObject() 
    100     skinsTool = getToolByName(portal, 'portal_skins') 
    101     pp = getToolByName(portal, 'portal_properties') 
    102     portal_css = getToolByName(portal, 'portal_css', None) 
    103     portal_js = getToolByName(portal, 'portal_javascripts', None) 
    104     # Get all properies, saving during installation, for uninstalling 
    105     actual_skin_name = getProperty(pp, 'uninstall_properties', 'q_actual_skin_name',default=SKIN_NAME) 
    106     initial_skin = getProperty(pp, 'uninstall_properties', 'q_default_skin',default="") 
    107     original_css_list = getProperty(pp, 'uninstall_properties', 'q_registered_css') 
    108     original_js_list = getProperty(pp, 'uninstall_properties', 'q_registered_js') 
    109     orig_left_slots = getProperty(pp, 'uninstall_properties','q_left_slots') 
    110     orig_right_slots = getProperty(pp, 'uninstall_properties','q_right_slots') 
    111     # Remove 'uninstall_properties' from portal_properties 
    112     if 'uninstall_properties' in pp.objectIds() : 
    113         pp.manage_delObjects(ids=['uninstall_properties',]) 
    114     # Uninstall skin 
    115     uninstallSkin(skinsTool, actual_skin_name, initial_skin) 
    116     # Unregister skin's CSS-es from portal_css. Only for Plone 2.1+ 
    117     if portal_css and DOES_COSTOMIZE_CSS: 
    118         uninstallResource(portal_css, original_css_list, CSS_LIST, portal_css.registerStylesheet) 
    119     # Unregister skin's JS-s from portal_javascripts. Only for Plone 2.1+ 
    120     if portal_js and DOES_COSTOMIZE_JS: 
    121         uninstallResource(portal_js, original_js_list, JS_LIST, portal_js.registerScript) 
    122     # Return site's column slots list unless Skin product installation 
    123     if orig_left_slots: 
    124         portal.left_slots = tuple(orig_left_slots) 
    125     if orig_right_slots: 
    126         portal.right_slots = tuple(orig_right_slots) 
     10    for extension_id in EXTENSION_PROFILES: 
     11        (portal_setup.aq_base).__of__(self).runAllImportStepsFromProfile('profile-%%s' %% extension_id) 
     12        transaction.savepoint(optimistic=True) 
  • qPloneSkinDump/branches/plone_3.0/skin_template/Extensions/utils.py

    r836 r935  
    4040    cfg = getConfiguration() 
    4141    instance_ipath = osp.join(cfg.instancehome, "import") 
    42     product_ipath = osp.join(cfg.instancehome, 'Products', PRODUCT_NAME, "import") 
     42    product_ipath = osp.join(PRODUCTS_PATH, PRODUCT_NAME, "import") 
    4343    # Check presence of Product import directory 
    4444    if not osp.isdir(product_ipath):         
     
    415415        res = pp[ps].getProperty(id, default) 
    416416    return res 
     417 
     418 
     419################################### 
     420## OLD INSTALL 
     421 
     422def prepareInstallation(portal, pp, out): 
     423    #uninstallOtherSkinProducts(portal) 
     424    if not ('uninstall_properties' in pp.objectIds()) : 
     425        pp.addPropertySheet(id='uninstall_properties', title= 'uninstall_properties') 
     426        print >> out, "Created 'portal_properties.uninstall_properties' PropertySheet (UP) for backup purpose" 
     427 
     428CHECKED_MESSAGE = "The base installation checkings completed." 
     429 
     430def uninstallOtherSkinProducts(portal): 
     431    qi=getToolByName(portal, 'portal_quickinstaller', None) 
     432    if not qi: 
     433        raise Exception("Can't work without QuickInstaller tool.") 
     434    # Get installed products 
     435    installed_products = [getattr(qi, p_dict['id']) \ 
     436                          for p_dict in qi.listInstalledProducts() 
     437                          if p_dict['id'] != PRODUCT_NAME] 
     438    seek_str = "%%s generated product" %% GENERATOR_PRODUCT 
     439    installed_skin_products = [] 
     440    # Looking for installed skin-products 
     441    for p in installed_products: 
     442        transcript = p.getTranscriptAsText() 
     443        if transcript.find(seek_str) >= 0 : 
     444            installed_skin_products.append(p.getId()) 
     445    # Uninstall found skin-products 
     446    if installed_skin_products: 
     447        qi.uninstallProducts(products=installed_skin_products) 
     448 
  • qPloneSkinDump/branches/plone_3.0/skin_template/config.py

    r503 r935  
     1import os 
    12## PLONE AND SKIN PRODUCT SPECIFIC CONSTANTS 
    23GLOBALS = globals() 
     
    1415## ['some/portlet1','some/portlet2'] - will change appropriate (left or right) 
    1516##                                     slot to listed portlets 
    16 LEFT_SLOTS = %(LEFT_SLOTS)s 
    17 RIGHT_SLOTS = %(RIGHT_SLOTS)s 
     17#LEFT_SLOTS = %(LEFT_SLOTS)s 
     18#RIGHT_SLOTS = %(RIGHT_SLOTS)s 
    1819 
    1920## Slot's list forming procedure. 
     
    2425#SLOT_FORMING = "blend_with_site" 
    2526#SLOT_FORMING = "replace" 
    26 SLOT_FORMING = "%(SLOT_FORMING)s" 
     27#SLOT_FORMING = "%(SLOT_FORMING)s" 
    2728 
    2829## Favour column for slots forming procedure. IMPORTANT only for 'Blend with...'  
     
    3738#MAIN_COLUMN = "right" 
    3839#MAIN_COLUMN = "both" 
    39 MAIN_COLUMN = "%(MAIN_COLUMN)s" 
     40#MAIN_COLUMN = "%(MAIN_COLUMN)s" 
    4041 
    4142 
     
    100101from Products.CMFCore.utils import getToolByName 
    101102FINAL_CUSTOMIZATION_FUNCTIONS = [] 
     103 
     104# site portlets registry 
     105SLOT_STRUCTURE = %(slot_structure)s 
     106 
     107# absolute file system path to product 
     108from Globals import package_home 
     109PRODUCTS_PATH = os.sep.join(package_home(GLOBALS).split(os.sep)[:-1]) 
  • qPloneSkinDump/branches/plone_3.0/skins/qploneskindump/qploneskindump_config.cpt

    r932 r935  
    187187            </fieldset> 
    188188 
    189             <fieldset tal:on-error="string:Slot customization not yet implemented for Plone 3.0+ :("
     189            <fieldset
    190190                <legend class="DoesCustomizeSlots"> 
    191191                    <input class="noborder" 
    192192                           type="checkbox" 
    193                            name="DoesCustomizeSlots" 
     193                           name="dump_portlets" 
    194194                           id="DoesCustomizeSlots" 
    195                            value="DOCustomizeSlots" 
    196                            tal:attributes="checked python:test(request.has_key('DoesCustomizeSlots'),'checked', nothing)"/> 
     195                           value="0" 
     196                           tal:attributes="checked request/dump_portlets|nothing" 
     197                           /> 
    197198                    <label for="DoesCustomizeSlots" 
    198                            style="font-size: 110%" 
    199                            i18n:translate="label_Slots">Customize portal slots in new product</label> 
    200                 </legend> 
    201                 <div class="formHelp" 
    202                      i18n:translate="help_DoesCustomizeSlots"> 
    203                   Customization portal slots in New Skin Product. 
    204                 </div> 
    205  
     199                           i18n:translate="label_dump_portlets">Dump porltets</label> 
     200                </legend> 
    206201                <p/> 
    207202                <div class="SlotsCustomizing"> 
    208203                    <label class="SlotsCustomizing_title" 
    209                           i18n:translate="label_SlotsCustomizing">Portal slots</label> 
     204                          i18n:translate="label_dump_policy">Dump Policy</label> 
    210205 
    211206                    <div i18n:translate="help_SlotsCustomizing" 
    212207                         class="formHelp"> 
    213                          BE VERY ACCURACY!   
    214                          Leave in the left and right slot lists only those portlets, which relate <br/> 
    215                          to your skin product and either bring with new product or is standard for Plone. 
    216                     </div> 
    217                     <div class="LeftSlotsCustomizing_title"> 
    218                         <label class="LeftSlotsCustomizing_title" 
    219                               i18n:translate="label_LeftsSlotCustomizing">Left portal slots customizing</label> 
    220                         <textarea class="LeftSlotsCustomizing_lines" 
    221                                rows="6" 
    222                                cols="35" 
    223                                name="left_slots:lines" 
    224                                value="" 
    225                                tal:define="value python:'\n'.join(request.get('left_slots', portal.left_slots))" 
    226                                tal:attributes="value value" 
    227                                tal:content="value" ></textarea> 
    228                     </div> 
    229                     <p/> 
    230                     <div class="RightSlotsCustomizing_title"> 
    231                         <label class="RightSlotsCustomizing_title" 
    232                               i18n:translate="label_RightSlotsCustomizing">Right portal slots customizing</label> 
    233                         <textarea class="RightSlotsCustomizing_lines" 
    234                                rows="6" 
    235                                cols="35" 
    236                                name="right_slots:lines" 
    237                                value="" 
    238                                tal:define="value python:'\n'.join(request.get('right_slots', portal.right_slots))" 
    239                                tal:attributes="value value"  
    240                                tal:content="value"></textarea> 
    241                     </div> 
    242  
    243                 </div> 
    244                 <p/> 
    245                 <div class="ColumnSlotsForming" 
    246                      tal:define="formers python:modules['Products.qPloneSkinDump.qPloneSkinDump'].getSlotsFormingList(); 
    247                                  value request/slot_forming|formers/default">  
    248                     <label i18n:translate="label_ColumnSlotsForming">Slot's list forming</label> 
    249                     <div i18n:translate="help_ColumnSlotsForming" 
    250                          class="formHelp"> 
    251                          Choose procedure of forming slots lists.<br/> 
    252                          Blend with skin - to SKIN PRODUCT's slots list added unknown slots from SITE.<br/> 
    253                          Blend with site - to SITE's slots list added unknown slots from SKIN PRODUCT.<br/> 
    254                          Replace - in left and right site's columns placed ONLY SKIN PRODUCT's slots. 
    255                     </div> 
    256                     <tal:loop tal:omit-tag="" 
    257                               tal:repeat="former formers/data"> 
    258                         <div> 
    259                             <input type="radio" 
    260                                    name="slot_forming" 
    261                                    value="#" 
    262                                    tal:attributes="value python:former[0]; 
    263                                                    checked python:test(former[0]==value,'checked', nothing)" /> 
    264                             <label class="ColumnSlotsForming_title" 
    265                                    i18n:translate="" 
    266                                    tal:content="python:former[1]"></label> 
    267                         </div> 
    268                     </tal:loop> 
    269                 </div> 
    270                 <p/> 
    271                 <div class="FavourColumn" 
    272                      tal:define="favour_columns python:modules['Products.qPloneSkinDump.qPloneSkinDump'].getMainColumnList(); 
    273                                  value request/main_column|favour_columns/default"> 
    274                     <label  i18n:translate="label_FavourColumn">Main column</label> 
    275                     <div i18n:translate="help_FavourColumn" 
    276                          class="formHelp"> 
    277                          Choose favour column for slots forming procedure. IMPORTANT only for 'Blend with...' formers.<br/> 
    278                          Left/Right - if find same slots in left and right columns - than slots move accordingly to left/right column.<br/> 
    279                          Both - if find same slots in left and right columns - than slots positionings as in Master's slots lists  
    280                          (from SKIN PRODUCT's slots for 'Blend with skin' procedure and SITE's slots for 'Blend with site'). 
    281                     </div> 
    282                     <tal:loop tal:omit-tag="" 
    283                               tal:repeat="favour favour_columns/data"> 
    284                         <div> 
    285                             <input type="radio" 
    286                                    name="main_column" 
    287                                    value="#" 
    288                                    tal:attributes="value python:favour[0]; 
    289                                                    checked python:test(favour[0]==value,'checked', nothing)" /> 
    290                             <label class="FavourColumn_title" 
    291                                    i18n:translate="" 
    292                                    tal:content="python:favour[1]"></label> 
    293                         </div> 
    294                     </tal:loop> 
    295                 </div> 
    296  
     208                     
     209                    </div> 
     210 
     211                    <input class="noborder" 
     212                           type="radio" 
     213                           name="dump_policy" 
     214                           value="root" 
     215                           id="root_dump_policy" 
     216                           onclick="javascript:document.getElementById('selection_widget').style.display='none';" 
     217                           tal:attributes="checked python:request.get('dump_policy', 'root') == 'root';" /> 
     218                    <label for="root_dump_policy" 
     219                           i18n:translate="label_root_dump_policy"> 
     220                        Dump portlets only for portal root 
     221                    </label> 
     222                    <br /> 
     223 
     224                    <input class="noborder" 
     225                           type="radio" 
     226                           name="dump_policy" 
     227                           value="all" 
     228                           id="all_dump_policy" 
     229                           onclick="javascript:document.getElementById('selection_widget').style.display='none';" 
     230                           tal:attributes="checked python:request.get('dump_policy', 'root') == 'all';" /> 
     231                    <label for="all_dump_policy" 
     232                           i18n:translate="label_all_dump_policy"> 
     233                        Dump portlets for the whole site content 
     234                    </label> 
     235                    <br /> 
     236 
     237                    <input class="noborder" 
     238                           type="radio" 
     239                           name="dump_policy" 
     240                           value="selection" 
     241                           id="selection_dump_policy" 
     242                           onclick="javascript:document.getElementById('selection_widget').style.display='';" 
     243                           tal:attributes="checked python:request.get('dump_policy', 'root') == 'selection';" /> 
     244                    <label for="selection_dump_policy" 
     245                           i18n:translate="label_selection_dump_policy"> 
     246                        Dump portlets only for selected content objects 
     247                    </label> 
     248                    <div id="selection_widget" style="display:none;" 
     249                         tal:define="friendly_types here/@@plone_portal_state/friendly_types; 
     250                                     options python:here.portal_catalog(portal_types=friendly_types)"> 
     251                        <select name="dump_objects" multiple="1" size="7"> 
     252                            <option value="root_path" 
     253                                    tal:content="string:[portal root]" 
     254                                    tal:attributes="value string:" /> 
     255                            <tal:options repeat="option options"> 
     256                            <option value="object_path" 
     257                                    tal:define="ppath python:'/'.join(option.getPath().split('/')[2:])" 
     258                                    tal:content="ppath" 
     259                                    tal:attributes="value ppath" /> 
     260                            </tal:options> 
     261                        </select> 
     262                    </div> 
     263                </div> 
    297264            </fieldset> 
    298265 
  • qPloneSkinDump/branches/plone_3.0/skins/qploneskindump/qploneskindump_config_script.cpy

    r503 r935  
    3737        right_slots = [i for i in right_slots if i] 
    3838 
     39# Exporting portlets 
     40dump_portlets = REQUEST.get('dump_portlets', 0) 
     41dump_policy = REQUEST.get('dump_policy', 'root') 
     42dump_portlets_selection = REQUEST.get('dump_objects', []) 
     43 
    3944# Exporting objects 
    4045import_policy = exporting_objects = None 
     
    6570              exporting_objects=exporting_objects, \ 
    6671              dump_CSS=dump_CSS, \ 
    67               dump_JS=dump_JS ) 
     72              dump_JS=dump_JS, \ 
     73              dump_portlets=dump_portlets, \ 
     74              dump_policy=dump_policy, 
     75              dump_portlets_selection=dump_portlets_selection) 
    6876 
    6977portal_status_message='"%s" Product successfully created.' % fs_product_name 
  • qPloneSkinDump/branches/plone_3.0/utils.py

    r894 r935  
    1 import os, re, string, sets 
     1import os, re, string, sets, time 
    22from App.config import getConfiguration 
    33from Products.CMFCore.utils import getToolByName 
     
    55from config import * 
    66from write_utils import writeProps, writeFileContent, writeObjectsMeta 
     7 
     8from zope.interface import providedBy 
     9from zope.schema import getFields 
     10from zope.component import getMultiAdapter, getUtility 
     11from plone.portlets.interfaces import IPortletAssignmentMapping, IPortletManager, IPortletDataProvider 
     12from plone.portlets.constants import CONTEXT_CATEGORY, GROUP_CATEGORY, CONTENT_TYPE_CATEGORY 
     13from plone.portlets.interfaces import ILocalPortletAssignmentManager 
    714 
    815CSS_PATTERN = re.compile("^.+\.css$") 
     
    4754    """ Return object's data.""" 
    4855    return meta_type in ['Image', 'File'] and obj.manage_FTPget() or obj.document_src() 
     56 
     57def extractPortletsFromContext(context, slot_structure, typesToShow): 
     58 
     59    info = {} 
     60 
     61    leftColumn = getUtility(IPortletManager, name=u'plone.leftcolumn', context=context) 
     62    rightColumn = getUtility(IPortletManager, name=u'plone.rightcolumn', context=context) 
     63 
     64    left = getMultiAdapter((context, leftColumn,), IPortletAssignmentMapping, context=context) 
     65    right = getMultiAdapter((context, rightColumn,), IPortletAssignmentMapping, context=context) 
     66 
     67    leftassignable = getMultiAdapter((context, leftColumn,), ILocalPortletAssignmentManager) 
     68    rightassignable = getMultiAdapter((context, rightColumn,), ILocalPortletAssignmentManager) 
     69 
     70    info['left_slots_blacklists'] = {GROUP_CATEGORY        : leftassignable.getBlacklistStatus(GROUP_CATEGORY), 
     71                                     CONTENT_TYPE_CATEGORY : leftassignable.getBlacklistStatus(CONTENT_TYPE_CATEGORY), 
     72                                     CONTEXT_CATEGORY      : leftassignable.getBlacklistStatus(CONTEXT_CATEGORY)} 
     73 
     74    info['right_slots_blacklists'] = {GROUP_CATEGORY        : rightassignable.getBlacklistStatus(GROUP_CATEGORY), 
     75                                      CONTENT_TYPE_CATEGORY : rightassignable.getBlacklistStatus(CONTENT_TYPE_CATEGORY), 
     76                                      CONTEXT_CATEGORY      : rightassignable.getBlacklistStatus(CONTEXT_CATEGORY)} 
     77 
     78    info['add_left_slots'] = [] 
     79    for name, portlet in left.items(): 
     80        for i in list(providedBy(portlet)): 
     81            if i.isOrExtends(IPortletDataProvider): 
     82                kwargs = {} 
     83                for fn, field in getFields(i).items(): 
     84                    kwargs[fn] = field.get(portlet) 
     85                info['add_left_slots'].append({'name'   : name, 
     86                                               'type'   : name, 
     87                                               'kwargs' : kwargs}) 
     88 
     89    info['add_right_slots'] = [] 
     90    for name, portlet in right.items(): 
     91        for i in list(providedBy(portlet)): 
     92            if i.isOrExtends(IPortletDataProvider): 
     93                kwargs = {} 
     94                for fn, field in getFields(i).items(): 
     95                    kwargs[fn] = field.get(portlet) 
     96                info['add_right_slots'].append({'name'   : name, 
     97                                                'type'   : name, 
     98                                                'kwargs' : kwargs}) 
     99 
     100    info['remove_left_slots'] = [] 
     101    info['remove_right_slots'] = [] 
     102 
     103    slot_structure.append(('/'.join(context.getPhysicalPath()[2:]), info)) 
     104 
     105    return slot_structure 
     106 
     107def dumpAllPortlets(context, slot_structure, typesToShow): 
     108    extractPortletsFromContext(context, slot_structure, typesToShow) 
     109    if getattr(context.aq_base, 'isPrincipiaFolderish', 0): 
     110        for id, obj in context.contentItems(): 
     111            if obj.portal_type in typesToShow: 
     112                dumpAllPortlets(obj, slot_structure, typesToShow) 
     113 
     114    return slot_structure 
     115 
     116def dumpPortlets(context, dump_policy, dump_portlets_selection): 
     117 
     118    portal = getToolByName(context, 'portal_url').getPortalObject() 
     119    portal_state = getMultiAdapter((portal, context.REQUEST), name=u'plone_portal_state') 
     120    typesToShow = portal_state.friendly_types() 
     121 
     122    slot_structure = [] 
     123    if dump_policy == 'root': 
     124        extractPortletsFromContext(portal, slot_structure, typesToShow) 
     125    elif dump_policy == 'all': 
     126        dumpAllPortlets(portal, slot_structure, typesToShow) 
     127    elif dump_policy == 'selection': 
     128        for ppath in dump_portlets_selection: 
     129            obj = portal.restrictedTraverse(ppath) 
     130            extractPortletsFromContext(obj, slot_structure, typesToShow) 
     131 
     132    return slot_structure 
    49133 
    50134def dumpSkin(context, \ 
     
    105189    f_tmpl.close() 
    106190    f_tmpl = open(f_path_write, 'w') 
    107     f_tmpl.write(tmpl % dict) 
     191    try: 
     192       f_tmpl.write(tmpl % dict) 
     193    except: 
     194        raise str(tmpl) 
    108195    f_tmpl.close() 
    109196 
     
    165252                   zmi_skin_name, zmi_base_skin_name, subdir,\ 
    166253                   doesCustomizeSlots, left_slots, right_slots, slot_forming, main_column, \ 
    167                    doesExportObjects, import_policy, dump_CSS, dump_JS): 
     254                   doesExportObjects, import_policy, dump_CSS, dump_JS, \ 
     255                   dump_portlets, dump_policy, dump_portlets_selection): 
    168256    """Create new skin-product's directory and  
    169257       copy skin-product template with little modification"""  
     
    181269        result_js_list, skin_js_regdata = getResourceListRegdata(context, subdir, 
    182270                                            JS_PATTERN, 'portal_javascripts', JS_REG_PROPS) 
     271 
     272    slots = () 
     273    if dump_portlets: 
     274        slots = dumpPortlets(context, dump_policy, dump_portlets_selection) 
     275 
    183276    # Get Slots customization information 
    184277    if not doesCustomizeSlots: 
     
    204297                ,"SLOT_FORMING" : slot_forming \ 
    205298                ,"MAIN_COLUMN" : main_column \ 
     299                ,"product_name" : productName \ 
     300                ,"skin_name" : productSkinName \ 
     301                ,"skin_name_capital" : '%s%s' % (productSkinName[0].upper(), productSkinName[1:]) \ 
     302                ,"product_name_lowercase" : productName.lower() \ 
     303                ,"viewlets_zcml" : '' \ 
     304                ,"version1" : time.strftime('%Y%m%d') + '-1' \ 
     305                ,"version2" : time.strftime('%Y%m%d') + '-2' \ 
     306                ,"slot_structure" : str(slots) 
    206307                } 
    207308    sp_updated_files = ['config.py' \ 
    208309                       ,'README.txt' \ 
     310                       ,'setuphandlers.py' \ 
     311                       ,'profiles.zcml' \ 
    209312                       ,ospJoin('Extensions', 'utils.py')\ 
    210                        ,ospJoin('Extensions', 'Install.py')] 
     313                       ,ospJoin('Extensions', 'Install.py')\ 
     314                       ,ospJoin('browser', 'interfaces.py')\ 
     315                       ,ospJoin('browser', 'viewlets.zcml')\ 
     316                       ,ospJoin('browser', 'configure.zcml')\ 
     317                       ,ospJoin('profiles', 'default', 'import_steps.xml')\ 
     318                       ,ospJoin('browser', 'configure.zcml') 
     319                       ] 
    211320    for fp in sp_updated_files: 
    212321        fillinFileTemplate(ospJoin(productPath, fp), dict=conf_dict)