def test_data_setter(self): folder = create(Builder('folder').titled(u'The Folder')) adapter = getAdapter(folder, IDataCollector, name='constrain_types_adapter') allowed_types = ['Collection', 'Document', 'Folder'] immediately_addable_types = ['Collection', 'Folder'] # Test when mode = 'ENABLED' adapter.setData( { 'mode': ENABLED, 'locally_allowed': allowed_types, 'immediately_addable': immediately_addable_types }, metadata=None) constrain_types = IConstrainTypes(folder) self.assertEquals(ENABLED, constrain_types.getConstrainTypesMode()) self.assertEquals(allowed_types, constrain_types.getLocallyAllowedTypes()) self.assertEquals(immediately_addable_types, constrain_types.getImmediatelyAddableTypes()) # Test when mode = 'DISABLED' # Results of getLocallyAllowedTypes() and getImmediatelyAddableTypes() # are determined by the portal type adapter.setData( { 'mode': DISABLED, 'locally_allowed': allowed_types, 'immediately_addable': immediately_addable_types }, metadata=None) constrain_types = IConstrainTypes(folder) self.assertEquals(DISABLED, constrain_types.getConstrainTypesMode()) self.assertEquals(self.standard_types, constrain_types.getLocallyAllowedTypes()) self.assertEquals(self.standard_types, constrain_types.getImmediatelyAddableTypes()) # Test when mode = 'ACQUIRE' # Results of getLocallyAllowedTypes() and getImmediatelyAddableTypes() # are determined by the parent object adapter.setData( { 'mode': ACQUIRE, 'locally_allowed': allowed_types, 'immediately_addable': immediately_addable_types }, metadata=None) constrain_types = IConstrainTypes(folder) self.assertEquals(ACQUIRE, constrain_types.getConstrainTypesMode()) self.assertEquals(self.standard_types, constrain_types.getLocallyAllowedTypes()) self.assertEquals(self.standard_types, constrain_types.getImmediatelyAddableTypes())
def _manageOtherMCCorrespondences(self, cfg): def _convert_to_real_other_mc_correspondences(annex_type): """ """ real_other_mc_correspondences = [] # we have a content_category id prefixed with cfg id # like meeting-config-test_-_annexes_types_-_item_annexes_-_annex # but we need the UID of the corresponding annexType for other_mc_correspondence in annex_type.other_mc_correspondences: steps = other_mc_correspondence.split(CAT_SEPARATOR) cfg_id = self.cfg_num_to_id(steps[0]) other_cfg = self.tool.get(cfg_id) corresponding_annex_type = other_cfg for step in steps[1:]: corresponding_annex_type = corresponding_annex_type[step] real_other_mc_correspondences.append( corresponding_annex_type.UID()) annex_type.other_mc_correspondences = set( real_other_mc_correspondences) # finish configuration of annexType.other_mc_correspondences # for ItemAnnexContentCategory and ItemAnnexContentSubcategory for annex_group in cfg.annexes_types.objectValues(): if 'ItemAnnexContentCategory' in IConstrainTypes( annex_group).getLocallyAllowedTypes(): for annex_type in annex_group.objectValues(): if annex_type.other_mc_correspondences: _convert_to_real_other_mc_correspondences(annex_type) for subType in annex_type.objectValues(): _convert_to_real_other_mc_correspondences(subType)
def _addableTypesInContext(self, addContext): allowed_types = _allowedTypes(self.request, addContext) constrain = IConstrainTypes(addContext, None) if constrain is None: return allowed_types locallyAllowed = constrain.getLocallyAllowedTypes() return [fti for fti in allowed_types if fti.getId() in locallyAllowed]
def get_constraintypes_config(self, obj): ctypes = IConstrainTypes(obj) return { 'mode': ctypes.getConstrainTypesMode(), 'locally allowed': set(ctypes.getLocallyAllowedTypes()), 'immediately addable': set(ctypes.getImmediatelyAddableTypes()) }
def _contentCanBeAdded(self, addContext, request): """Find out if content can be added either by local constraints on the context or by allowed_content_types on the FTI. """ constrain = IConstrainTypes(addContext, None) if constrain is None: return _allowedTypes(request, addContext) return constrain.getLocallyAllowedTypes()
def _locallyAllowedTypes(self, addContext): addContext = addContext or self.context allowed_types = _allowedTypes(self.request, addContext) constrain = IConstrainTypes(addContext, None) if constrain is None: return allowed_types locallyAllowed = constrain.getLocallyAllowedTypes() # logger.info("locallyAllowed: {}".format(locallyAllowed)) return locallyAllowed
def _migrateMeetingCategoryToDX(self): '''Migrate from AT MeetingCategory to DX meetingcategory.''' logger.info('Migrating MeetingCategory from AT to DX...') # update item classifier # migrate references pghandler = ZLogHandler(steps=100) brains = self.portal.reference_catalog( relationship='ItemClassification') pghandler.init('Updating field MeetingItem.classifier...', len(brains)) pghandler.info('Updating field MeetingItem.classifier...') i = 0 for brain in brains: i += 1 pghandler.report(i) relation = brain.getObject() item = relation.getSourceObject() classifier = relation.getTargetObject() item.setClassifier(classifier.getId()) item.reindexObject(idxs=['getRawClassifier']) # deleteReferences in a second phase for brain in brains: relation = brain.getObject() item = relation.getSourceObject() item.deleteReferences('ItemClassification') pghandler.finish() logger.info('Migrating categories and classifiers in configuration...') # make sure new portal_type meetingcategory is installed self.ps.runImportStepFromProfile( 'profile-Products.PloneMeeting:default', 'typeinfo') # make sure no workflow used for meetingcategory self.wfTool.setChainForPortalTypes(('meetingcategory', ), ('', )) # adapt allowed_types for each MeetingConfig.categories/classifiers folders for cfg in self.tool.objectValues('MeetingConfig'): for folder_id in ('categories', 'classifiers'): constrain = IConstrainTypes(getattr(cfg, folder_id)) constrain.setConstrainTypesMode(1) allowedTypes = ['meetingcategory'] constrain.setLocallyAllowedTypes(allowedTypes) constrain.setImmediatelyAddableTypes(allowedTypes) # migrate to DX pac_migrate(self.portal, MeetingCategoryMigrator) self.removeUnusedPortalTypes(portal_types=['MeetingCategory']) # add meetingcategory to types_not_searched props = api.portal.get_tool('portal_properties').site_properties nsTypes = props.getProperty('types_not_searched') if 'meetingcategory' not in nsTypes: nsTypes = list(nsTypes) # MeetingCategory was removed by removeUnusedPortalTypes nsTypes.append('meetingcategory') props.manage_changeProperties(types_not_searched=tuple(nsTypes)) logger.info('Done.')
def _getMenuItemsForContext(self, context, request): """Return menu item entries for the context only.""" results = [] if context is not None: allowed = [] constraints = [] haveMore = False include = None allowed = context.allowedContentTypes() constraints = IConstrainTypes(context, None) if constraints is not None: include = constraints.getImmediatelyAddableTypes() if len(include) < len(allowed): haveMore = True results = self._addable_types(context, request, allowed, include) if haveMore: url = '%s/folder_factories' % (context.absolute_url(),) results.append({ 'title' : _(u'folder_add_more', default=u'More\u2026'), 'description' : _(u'Show all available content types'), 'action' : url, 'selected' : False, 'icon' : None, 'extra' : {'id': 'more', 'separator': None, 'class': ''}, 'submenu' : None, }) selectableConstraints = ISelectableConstrainTypes(context, None) if selectableConstraints is not None: if selectableConstraints.canSetConstrainTypes() and \ selectableConstraints.getDefaultAddableTypes(): url = '%s/folder_constraintypes_form' % (context.absolute_url(),) results.append({'title' : _(u'folder_add_settings', default=u'Restrictions\u2026'), 'description' : _(u'title_configure_addable_content_types', default=u'Configure which content types can be added here'), 'action' : url, 'selected' : False, 'icon' : None, 'extra' : {'id': 'settings', 'separator': None, 'class': ''}, 'submenu' : None, }) return results
def _fixFacetedFoldersConstrainTypes(self): """Fix constrainTypes for every faceted folder stored in user personnal folder.""" logger.info( 'Updating searches_... folders constraintypes for every users...') for cfg in self.tool.objectValues('MeetingConfig'): folders = cfg._get_all_meeting_folders() for folder in folders: sub_folders = [ sub_folder for sub_folder in folder.objectValues('ATFolder') if sub_folder.getId().startswith('searches_') ] for sub_folder in sub_folders: constrain = IConstrainTypes(sub_folder) constrain.setConstrainTypesMode(1) allowedTypes = [] constrain.setLocallyAllowedTypes(allowedTypes) constrain.setImmediatelyAddableTypes(allowedTypes) logger.info('Done.')
def install_demo(context): """ """ if context.readDataFile('collectivedocumentgenerator_demo_marker.txt') is None: return portal = api.portal.get() if not hasattr(portal, 'podtemplates'): templates_folder = api.content.create( type='Folder', title=_(u'POD Templates'), id='podtemplates', container=portal, exclude_from_nav=True ) templates_folder.setTitle('POD Templates') templates_folder.reindexObject() pod_folder = getattr(portal, 'podtemplates') constrain_types = IConstrainTypes(pod_folder) constrain_types.setConstrainTypesMode(1) constrain_types.setLocallyAllowedTypes(POD_TEMPLATE_TYPES.keys()) constrain_types.setImmediatelyAddableTypes(POD_TEMPLATE_TYPES.keys()) # Create some test content style_template_id = 'test_style_template' if not hasattr(pod_folder, style_template_id): api.content.create( type='StyleTemplate', id=style_template_id, title='Styles', odt_file=NamedBlobFile( data=context.readDataFile('templates/styles.odt'), contentType='application/vnd.oasis.opendocument.text', filename=u'styles.odt', ), container=pod_folder, exclude_from_nav=True ) style_template = getattr(pod_folder, style_template_id) style_template_id = 'test_style_template_2' if not hasattr(pod_folder, style_template_id): api.content.create( type='StyleTemplate', id=style_template_id, title=_(u'Styles n°2'), odt_file=NamedBlobFile( data=context.readDataFile('templates/styles_2.odt'), contentType='application/vnd.oasis.opendocument.text', filename=u'styles_2.odt', ), container=pod_folder, exclude_from_nav=True ) sub_template_id = 'sub_template' if not hasattr(pod_folder, sub_template_id): api.content.create( type='SubTemplate', id=sub_template_id, title=_(u'Header'), odt_file=NamedBlobFile( data=context.readDataFile('templates/sub_template.odt'), contentType='application/vnd.oasis.opendocument.text', filename=u'sub_template.odt', ), container=pod_folder, exclude_from_nav=True, style_template=[style_template.UID()], ) sub_template = getattr(pod_folder, sub_template_id) if not hasattr(pod_folder, 'loop_template'): api.content.create( type='MailingLoopTemplate', id='loop_template', title=_(u'Mailing loop template'), odt_file=NamedBlobFile( data=context.readDataFile('templates/mailing.odt'), contentType='application/vnd.oasis.opendocument.text', filename=u'mailing.odt', ), container=pod_folder, exclude_from_nav=True, style_template=[style_template.UID()], ) loop_template = getattr(pod_folder, 'loop_template') if not hasattr(pod_folder, 'test_template'): api.content.create( type='PODTemplate', id='test_template', title=_(u'General template'), odt_file=NamedBlobFile( data=context.readDataFile('templates/modele_general.odt'), contentType='application/vnd.oasis.opendocument.text', filename=u'modele_general.odt', ), container=pod_folder, exclude_from_nav=True, ) if not hasattr(pod_folder, 'test_template_multiple'): api.content.create( type='ConfigurablePODTemplate', id='test_template_multiple', title=_(u'Multiple format template'), odt_file=NamedBlobFile( data=context.readDataFile('templates/modele_general.odt'), contentType='application/vnd.oasis.opendocument.text', filename=u'modele_general.odt', ), container=pod_folder, exclude_from_nav=True, pod_formats=['odt', 'pdf', 'doc', 'docx'], pod_portal_types=['Document'], style_template=[style_template.UID()], merge_templates=[ { 'template': sub_template.UID(), 'pod_context_name': 'header', 'do_rendering': True, } ], ) if not hasattr(pod_folder, 'test_template_bis'): api.content.create( type='ConfigurablePODTemplate', id='test_template_bis', title=_(u'Collection template'), odt_file=NamedBlobFile( data=context.readDataFile(safe_unicode('templates/modèle_collection.odt')), contentType='application/vnd.oasis.opendocument.text', filename=u'modèle_collection.odt', ), container=pod_folder, exclude_from_nav=True, pod_formats=['odt', 'pdf', ], pod_portal_types=['Collection', 'Folder'], style_template=[style_template.UID()], merge_templates=[ { 'template': sub_template.UID(), 'pod_context_name': 'header', 'do_rendering': False, } ], context_variables=[ { 'name': 'details', 'value': '1', } ], ) if not hasattr(pod_folder, 'test_ods_template'): api.content.create( type='ConfigurablePODTemplate', id='test_ods_template', title=_(u'Spreadsheet template'), odt_file=NamedBlobFile( data=context.readDataFile('templates/modele_general.ods'), contentType='application/vnd.oasis.opendocument.spreadsheet', filename=u'modele_general.ods', ), container=pod_folder, exclude_from_nav=True, pod_formats=['ods', 'xls', ], pod_portal_types=['Document'], style_template=[style_template.UID()], ) if not hasattr(pod_folder, 'test_template_possibly_mailed'): api.content.create( type='ConfigurablePODTemplate', id='test_template_possibly_mailed', title=_(u'Possibly mailed template'), odt_file=NamedBlobFile( data=context.readDataFile('templates/possibly_mailed_model.odt'), contentType='application/vnd.oasis.opendocument.text', filename=u'possibly_mailed_model.odt', ), container=pod_folder, exclude_from_nav=True, pod_formats=['odt'], pod_portal_types=['Folder'], mailing_loop_template=loop_template.UID(), context_variables=[ { 'name': 'details', 'value': '1', } ], ) if not hasattr(pod_folder, 'test_template_reusable'): api.content.create( type='ConfigurablePODTemplate', id='test_template_reusable', title=_(u'Reusable template'), odt_file=NamedBlobFile( data=context.readDataFile('templates/modele_general.odt'), contentType='application/vnd.oasis.opendocument.text', filename=u'modele_general.odt', ), is_reusable=True, container=pod_folder, pod_formats=['odt'], pod_portal_types=['Folder'], exclude_from_nav=True ) reusable_template = getattr(pod_folder, 'test_template_reusable') if not hasattr(pod_folder, 'test_template_reuse'): api.content.create( type='ConfigurablePODTemplate', id='test_template_reuse', title=_(u'Reuse Test Template'), container=pod_folder, exclude_from_nav=True, pod_formats=['odt', 'pdf', 'doc', 'docx'], pod_portal_types=['Document'], pod_template_to_use=reusable_template.UID() )
def get_addable_items(self): """ Return menu item entries in a TAL-friendly form. """ context = self.context request = self.request factories_view = getMultiAdapter( (context, request), name='folder_factories', ) include = None addContext = factories_view.add_context() constraints = IConstrainTypes(addContext, None) if constraints is not None: include = constraints.getImmediatelyAddableTypes() results = factories_view.addable_types(include=include) results_with_icons = [] for result in results: result['icon'] = 'menu-item-icon {0}'.format(self.icon('plus')) results_with_icons.append(result) results = results_with_icons constraints = ISelectableConstrainTypes(addContext, None) if constraints is not None: if constraints.canSetConstrainTypes() and \ constraints.getDefaultAddableTypes(): url = '{0}/folder_constraintypes_form'.format( addContext.absolute_url(), ) results.append({ 'title': _(u'folder_add_settings', default=u'Restrictions'), 'description': _( u'title_configure_addable_content_types', default=u'Configure which content types can be ' u'added here', ), 'action': url, 'selected': False, 'icon': 'menu-item-icon {0}'.format(self.icon('cog')), 'id': 'settings', 'extra': { 'id': 'plone-contentmenu-settings', 'separator': None, 'class': '', }, 'submenu': None, }) # Also add a menu item to add items to the default page context_state = getMultiAdapter( (context, request), name='plone_context_state', ) if context_state.is_structural_folder() and \ context_state.is_default_page() and \ self._contentCanBeAdded(context, request): results.append({ 'title': _(u'default_page_folder', default=u'Add item to default page'), 'description': _( u'desc_default_page_folder', default=u'If the default page is also a folder, ' u'add items to it from here.', ), 'action': context.absolute_url() + '/@@folder_factories', 'selected': False, 'icon': 'menu-item-icon {0}'.format(self.icon('cog')), 'id': 'special', 'extra': { 'id': 'plone-contentmenu-add-to-default-page', 'separator': None, 'class': 'pat-plone-modal', }, 'submenu': None, }) return results
def getMenuItems(self, context, request): """Return menu item entries in a TAL-friendly form.""" results = BaseFactoriesMenu.getMenuItems(self, context, request) factories_view = getMultiAdapter((context, request), name='folder_factories') haveMore = False include = None addContext = factories_view.default_page_add_context() if not addContext: return results allowedTypes = _allowedTypes(request, addContext) constraints = IConstrainTypes(addContext, None) if constraints is not None: include = constraints.getImmediatelyAddableTypes() if len(include) < len(allowedTypes): haveMore = True results.append({ 'title': _p(u'folder_add_to_default_page', default=u'Add to default page'), 'description': _p(u'Add content to the default page'), 'action': None, 'selected': False, 'icon': None, 'extra': { 'id': 'add-to-default', 'separator': 'actionSeparator', 'class': '' }, 'submenu': None, }) results += factories_view.default_page_addable_types(include=include) if haveMore: url = '%s/folder_factories' % (addContext.absolute_url(), ) results.append({ 'title': _p(u'folder_add_more', default=u'More\u2026'), 'description': _p(u'Show all available content types'), 'action': url, 'selected': False, 'icon': None, 'extra': { 'id': 'more', 'separator': None, 'class': '' }, 'submenu': None, }) constraints = ISelectableConstrainTypes(addContext, None) if constraints is not None: if constraints.canSetConstrainTypes( ) and constraints.getDefaultAddableTypes(): url = '%s/folder_constraintypes_form' % ( addContext.absolute_url(), ) results.append({ 'title': _p(u'folder_add_settings', default=u'Restrictions\u2026'), 'description': _p(u'title_configure_addable_content_types', default= u'Configure which content types can be added here'), 'action': url, 'selected': False, 'icon': None, 'extra': { 'id': 'settings', 'separator': None, 'class': '' }, 'submenu': None, }) return results
def getMenuItems(self, context, request): """Return menu item entries in a TAL-friendly form.""" factories_view = getMultiAdapter((context, request), name='folder_factories') haveMore = False include = None addContext = factories_view.add_context() allowedTypes = _allowedTypes(request, addContext) constraints = IConstrainTypes(addContext, None) if constraints is not None: include = constraints.getImmediatelyAddableTypes() if len(include) < len(allowedTypes): haveMore = True results = factories_view.addable_types(include=include) if haveMore: url = '%s/folder_factories' % (addContext.absolute_url(), ) results.append({ 'title': _(u'folder_add_more', default=u'More\u2026'), 'description': _(u'Show all available content types'), 'action': url, 'selected': False, 'icon': None, 'extra': { 'id': 'plone-contentmenu-more', 'separator': None, 'class': '' }, 'submenu': None, }) constraints = ISelectableConstrainTypes(addContext, None) if constraints is not None: if constraints.canSetConstrainTypes() and \ constraints.getDefaultAddableTypes(): url = '%s/folder_constraintypes_form' % ( addContext.absolute_url(), ) results.append({ 'title': _(u'folder_add_settings', default=u'Restrictions\u2026'), 'description': _(u'title_configure_addable_content_types', default=u'Configure which content types can be ' u'added here'), 'action': url, 'selected': False, 'icon': None, 'extra': { 'id': 'plone-contentmenu-settings', 'separator': None, 'class': '' }, 'submenu': None, }) # Also add a menu item to add items to the default page context_state = getMultiAdapter((context, request), name='plone_context_state') if context_state.is_structural_folder() and \ context_state.is_default_page() and \ self._contentCanBeAdded(context, request): results.append({ 'title': _(u'default_page_folder', default=u'Add item to default page'), 'description': _(u'desc_default_page_folder', default=u'If the default page is also a folder, ' u'add items to it from here.'), 'action': context.absolute_url() + '/@@folder_factories', 'selected': False, 'icon': None, 'extra': { 'id': 'plone-contentmenu-add-to-default-page', 'separator': None, 'class': 'pat-plone-modal' }, 'submenu': None, }) return results