def test_isMixedIn(self): self.assertTrue( isinstance(self.af, constraintypes.ConstrainTypesMixin), "ConstrainTypesMixin was not mixed in to ATFolder") self.assertTrue( ISelectableConstrainTypes.providedBy(self.af), "ISelectableConstrainTypes not implemented by ATFolder instance")
def test_isMixedIn(self): self.failUnless(isinstance(self.af, constraintypes.ConstrainTypesMixin), "ConstrainTypesMixin was not mixed in to ATFolder") self.failUnless(ZopeTwoISelectableConstrainTypes.isImplementedBy(self.af), "ISelectableConstrainTypes not implemented by ATFolder instance") self.failUnless(ISelectableConstrainTypes.providedBy(self.af), "ISelectableConstrainTypes not implemented by ATFolder instance")
class FormContentAdapter(object): def __init__(self, context): self.context = ISelectableConstrainTypes(context) @property def constrain_types_mode(self): return self.context.getConstrainTypesMode() @property def allowed_types(self): return self.context.getLocallyAllowedTypes() @property def secondary_types(self): immediately_addable = self.context.getImmediatelyAddableTypes() return [t for t in self.context.getLocallyAllowedTypes() if t not in immediately_addable]
def testMoreNotIncludedWhenNotNecessary(self): constraints = ISelectableConstrainTypes(self.folder) constraints.setConstrainTypesMode(1) constraints.setLocallyAllowedTypes(('Document',)) constraints.setImmediatelyAddableTypes(('Document',)) actions = self.menu.getMenuItems(self.folder, self.request) self.assertEqual(len(actions), 2) self.assertEqual(actions[0]['extra']['id'], 'document') self.assertEqual(actions[1]['extra']['id'], 'settings')
def testNonStructualFolderShowsParent(self): self.folder.invokeFactory('Folder', 'folder1') directlyProvides(self.folder.folder1, INonStructuralFolder) constraints = ISelectableConstrainTypes(self.folder.folder1) constraints.setConstrainTypesMode(1) constraints.setLocallyAllowedTypes(('Document',)) constraints.setImmediatelyAddableTypes(('Document',)) actions = self.menu.getMenuItems(self.folder.folder1, self.request) self.assertEqual(len(actions), 0)
def testNonStructualFolderShowsParent(self): self.folder.invokeFactory('Folder', 'folder1') directlyProvides(self.folder.folder1, INonStructuralFolder) constraints = ISelectableConstrainTypes(self.folder.folder1) constraints.setConstrainTypesMode(1) constraints.setLocallyAllowedTypes(('Document',)) constraints.setImmediatelyAddableTypes(('Document',)) actions = self.menu.getMenuItems(self.folder.folder1, self.request) action_ids = [a['extra']['id'] for a in actions] self.assertTrue('event' in action_ids)
def testMoreIncluded(self): constraints = ISelectableConstrainTypes(self.folder) constraints.setConstrainTypesMode(1) constraints.setLocallyAllowedTypes(('Document', 'Image',)) constraints.setImmediatelyAddableTypes(('Document',)) actions = self.menu.getMenuItems(self.folder, self.request) self.failIf('image' in [a['extra']['id'] for a in actions]) self.failUnless('document' in [a['extra']['id'] for a in actions]) self.failUnless('more' in [a['extra']['id'] for a in actions]) self.failUnless('settings' in [a['extra']['id'] for a in actions])
def testAddMenuWithNothingToAddButWithAvailableConstrainSettings(self): constraints = ISelectableConstrainTypes(self.folder) constraints.setConstrainTypesMode(1) constraints.setLocallyAllowedTypes(()) constraints.setImmediatelyAddableTypes(()) items = self.menu.getMenuItems(self.folder, self.request) factoriesMenuItem = [ i for i in items if i['extra']['id'] == 'plone-contentmenu-factories'][0] self.assertEqual(len(factoriesMenuItem['submenu']), 1) self.assertEqual(factoriesMenuItem['submenu'][0]['extra']['id'], 'plone-contentmenu-settings')
def handleSave(self, action): data, errors = self.extractData() if errors: return immediately_addable_types = [t for t in data['current_prefer'] if t not in data['current_allow']] locally_allowed_types = data['current_prefer'] aspect = ISelectableConstrainTypes(self.context) aspect.setConstrainTypesMode(data['constrain_types_mode']) aspect.setLocallyAllowedTypes(locally_allowed_types) aspect.setImmediatelyAddableTypes(immediately_addable_types)
def testAddMenuWithNothingToAddButWithAvailableMorePage(self): constraints = ISelectableConstrainTypes(self.folder) constraints.setConstrainTypesMode(1) constraints.setLocallyAllowedTypes(('Document',)) constraints.setImmediatelyAddableTypes(()) self.folder.manage_permission('Modify constrain types', ('Manager',)) setRoles(self.portal, TEST_USER_ID, ['Contributor']) items = self.menu.getMenuItems(self.folder, self.request) factoriesMenuItem = [i for i in items if i['extra']['id'] == 'plone-contentmenu-factories'][0] self.assertEqual(len(factoriesMenuItem['submenu']), 1) self.assertEqual(factoriesMenuItem['submenu'][0]['extra']['id'], 'plone-contentmenu-more')
def testMoreIncluded(self): constraints = ISelectableConstrainTypes(self.folder) constraints.setConstrainTypesMode(1) constraints.setLocallyAllowedTypes(('Document', 'Image',)) constraints.setImmediatelyAddableTypes(('Document',)) actions = self.menu.getMenuItems(self.folder, self.request) self.assertFalse('image' in [a['extra']['id'] for a in actions]) self.assertTrue('document' in [a['extra']['id'] for a in actions]) self.assertTrue( 'plone-contentmenu-more' in [a['extra']['id'] for a in actions] ) self.assertTrue( 'plone-contentmenu-settings' in [a['extra']['id'] for a in actions] )
def testAddMenuWithAddViewExpr(self): # we need a dummy to test this - should test that if the item does not # support constrain types and there is constraints = ISelectableConstrainTypes(self.folder) constraints.setConstrainTypesMode(1) constraints.setLocallyAllowedTypes(('Document',)) constraints.setImmediatelyAddableTypes(('Document',)) self.folder.manage_permission('Modify constrain types', ('Manager',)) self.portal.portal_types['Document']._setPropValue( 'add_view_expr', 'string:custom_expr') items = self.menu.getMenuItems(self.folder, self.request) factoriesMenuItem = [ i for i in items if i['extra']['id'] == 'plone-contentmenu-factories'][0] self.assertEqual(factoriesMenuItem['submenu'][0]['action'], 'custom_expr')
def __call__(self): if hasattr(self.context.aq_base, CAROUSEL_ID): carousel = getattr(self.context, CAROUSEL_ID) else: pt = getToolByName(self.context, 'portal_types') newid = pt.constructContent( type_name='Folder', container=self.context, id='carousel', title='Carousel Banners' ) carousel = getattr(self.context, newid) # exclude the (Archetypes or Dexterity) folder from navigation if hasattr(aq_base(carousel), 'setExcludeFromNav'): carousel.setExcludeFromNav(True) elif hasattr(aq_base(carousel), 'exclude_from_nav'): carousel.exclude_from_nav = True # mark the new folder as a Carousel folder alsoProvides(carousel, ICarouselFolder) # make sure Carousel banners are addable within the new folder addPermissionsForRole(carousel, 'Manager', ('Carousel: Add Carousel Banner',)) addPermissionsForRole(carousel, 'Site Administrator', ('Carousel: Add Carousel Banner',)) addPermissionsForRole(carousel, 'Owner', ('Carousel: Add Carousel Banner',)) addPermissionsForRole(carousel, 'Contributor', ('Carousel: Add Carousel Banner',)) addPermissionsForRole(carousel, 'Editor', ('Carousel: Add Carousel Banner',)) # make sure *only* Carousel banners are addable aspect = ISelectableConstrainTypes(carousel) aspect.setConstrainTypesMode(1) aspect.setLocallyAllowedTypes(['Carousel Banner']) aspect.setImmediatelyAddableTypes(['Carousel Banner']) carousel.reindexObject() self.request.RESPONSE.redirect( carousel.absolute_url() + '/@@edit-carousel' )
def handleSave(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return allowed_types = data['allowed_types'] immediately_addable = [ t for t in allowed_types if t not in data['secondary_types']] aspect = ISelectableConstrainTypes(self.context) aspect.setConstrainTypesMode(data['constrain_types_mode']) aspect.setLocallyAllowedTypes(allowed_types) aspect.setImmediatelyAddableTypes(immediately_addable) contextURL = self.context.absolute_url() self.request.response.redirect(contextURL)
def test_create_constraints(self): """Test the constraints when creating content.""" from plone.api.exc import InvalidParameterError from plone.api.exc import MissingParameterError # This will definitely fail with self.assertRaises(MissingParameterError): api.content.create() # Check the contraints for the type container with self.assertRaises(MissingParameterError): api.content.create( type='Document', id='test-doc', ) # Check the contraints for the type parameter container = mock.Mock() with self.assertRaises(MissingParameterError): api.content.create( container=container, id='test-doc', ) # Check the contraints for id and title parameters with self.assertRaises(MissingParameterError): api.content.create(container=container, type='Document') # Check the contraints for allowed types in the container container = self.events with self.assertRaises(InvalidParameterError): api.content.create( container=container, type='foo', id='test-foo', ) # Check the contraints for allowed types in the container if # the container is the portal container = self.portal with self.assertRaises(InvalidParameterError) as cm: api.content.create(container=container, type='foo', id='test-foo') # Check if the underlying error message is included # in the InvalidParameterError message self.assertIn("No such content type: foo", cm.exception.message) # Check the contraints for allowed types in the container # Create a folder folder = api.content.create(container=container, type='Folder', id='test-folder') assert folder # Constraint the allowed types ENABLED = 1 if getattr(aq_base(folder), 'setConstrainTypesMode', None): # AT folder.setConstrainTypesMode(ENABLED) folder.setLocallyAllowedTypes(('News Item', )) else: # DX from Products.CMFPlone.interfaces import ISelectableConstrainTypes constraints = ISelectableConstrainTypes(folder) constraints.setConstrainTypesMode(ENABLED) constraints.setLocallyAllowedTypes(('News Item', )) with self.assertRaises(InvalidParameterError): api.content.create(container=folder, type='Document', id='test-doc')
def __init__(self, context): self.context = ISelectableConstrainTypes(context)
def notiziaCreateHandler(notizia, event): """ Complete content type notizia setup on added event, generating missing folders, fields, etc. @param notizia: Content item @param event: Event that triggers the method (onAdded event) """ if "multimedia" not in notizia.keys(): multimedia = api.content.create(type="Document", title="Multimedia", container=notizia) create_default_blocks(context=multimedia) constraintsMultimedia = ISelectableConstrainTypes(multimedia) constraintsMultimedia.setConstrainTypesMode(1) constraintsMultimedia.setLocallyAllowedTypes(("Link", "Image")) if "documenti-allegati" not in notizia.keys(): documenti = api.content.create(type="Document", title="Documenti allegati", container=notizia) create_default_blocks(context=documenti) constraintsDocumenti = ISelectableConstrainTypes(documenti) constraintsDocumenti.setConstrainTypesMode(1) constraintsDocumenti.setLocallyAllowedTypes(("File", "Image"))
def test_create_constraints(self): """Test the constraints when creating content.""" from plone.api.exc import InvalidParameterError from plone.api.exc import MissingParameterError # This will definitely fail with self.assertRaises(MissingParameterError): api.content.create() # Check the constraints for the type container with self.assertRaises(MissingParameterError): api.content.create( type='Document', id='test-doc', ) # Check the constraints for the type parameter container = mock.Mock() with self.assertRaises(MissingParameterError): api.content.create( container=container, id='test-doc', ) # Check the constraints for id and title parameters with self.assertRaises(MissingParameterError): api.content.create( container=container, type='Document', ) # Check the constraints for allowed types in the container container = self.events with self.assertRaises(InvalidParameterError): api.content.create( container=container, type='foo', id='test-foo', ) # Check the constraints for allowed types in the container if # the container is the portal container = self.portal with self.assertRaises(InvalidParameterError) as cm: api.content.create( container=container, type='foo', id='test-foo', ) # Check if the underlying error message is included # in the InvalidParameterError message self.assertIn( 'No such content type: foo', str(cm.exception), ) # Check the constraints for allowed types in the container # Create a folder folder = api.content.create( container=container, type='Folder', id='test-folder', ) assert folder # Constraint the allowed types ENABLED = 1 if getattr(aq_base(folder), 'setConstrainTypesMode', None): # AT folder.setConstrainTypesMode(ENABLED) folder.setLocallyAllowedTypes(('News Item', )) else: # DX from Products.CMFPlone.interfaces import ISelectableConstrainTypes constraints = ISelectableConstrainTypes(folder) constraints.setConstrainTypesMode(ENABLED) constraints.setLocallyAllowedTypes(('News Item', )) with self.assertRaises(InvalidParameterError): api.content.create( container=folder, type='Document', id='test-doc', )
def program_added(o, event): # doesn't work in the IObjectCreatedEvent # fix which types can be contained in a Program aspect = ISelectableConstrainTypes(o) aspect.setConstrainTypesMode(DISABLED)
def create_organ_content(og_unit, og_type, og_string, og_title, og_id): """ Creates all structure based on organ type """ open_og = api.content.create(type='genweb.organs.organgovern', title=og_title, id=og_id, container=og_unit, safe_id=True) open_og.acronim = og_string open_og.descripcioOrgan = getLoremIpsum(1, 'medium', 'plaintext') open_og.fromMail = '*****@*****.**' open_og.organType = og_type open_og.logoOrgan = getRandomImage(200, 200) open_og.visiblefields = True open_og.eventsColor = 'green' open_og.membresOrgan = RichTextValue(getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output open_og.convidatsPermanentsOrgan = RichTextValue( getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output open_og.adrecaLlista = '*****@*****.**' session_open = api.content.create(type='genweb.organs.sessio', id='planificada', title='Sessió Planificada', container=open_og, safe_id=True) session_open.membresConvocats = RichTextValue( getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output session_open.membresConvidats = RichTextValue( getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output session_open.llistaExcusats = RichTextValue( getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output session_open.assistents = RichTextValue(getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output session_open.noAssistents = RichTextValue(getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output session_open.adrecaLlista = '*****@*****.**' session_open.llocConvocatoria = 'Barcelona' session_open.numSessio = '01' acc = IEventAccessor(session_open) tz = pytz.timezone("Europe/Vienna") acc.start = tz.localize(datetime(2018, 11, 18, 10, 0)) acc.end = tz.localize(datetime(2018, 11, 20, 10, 0)) acc.timezone = "Europe/Vienna" punt = api.content.create(type='genweb.organs.punt', id='punt', title='Punt Exemple', container=session_open) punt.proposalPoint = 1 punt.defaultContent = RichTextValue(getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output punt.estatsLlista = u'Esborrany' # For working test code. If not added, Plone works, but test dont. constraints = ISelectableConstrainTypes(punt) constraints.setConstrainTypesMode(1) constraints.setLocallyAllowedTypes( ('genweb.organs.subpunt', 'genweb.organs.acord', 'genweb.organs.file', 'genweb.organs.document')) document_public = api.content.create(type='genweb.organs.document', id='docpublic', title='Document contingut public', container=punt) document_public.description = u"Lorem Ipsum description" document_public.defaultContent = RichTextValue( getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output document_restringit = api.content.create( type='genweb.organs.document', id='docrestringit', title='Document contingut restringit', container=punt) document_restringit.description = u"Lorem Ipsum description" document_restringit.alternateContent = RichTextValue( getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output document_both = api.content.create( type='genweb.organs.document', id='docboth', title='Document contingut public i restringit', container=punt) document_both.description = u"Lorem Ipsum description" document_both.defaultContent = RichTextValue( getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output document_both.alternateContent = RichTextValue( getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output # For working tests code # constraints = ISelectableConstrainTypes(punt) # constraints.setConstrainTypesMode(1) # constraints.setLocallyAllowedTypes(('genweb.organs.subpunt', 'genweb.organs.acord', 'genweb.organs.file', 'genweb.organs.document')) subpunt = api.content.create(type='genweb.organs.subpunt', id='subpunt', title='SubPunt Exemple', container=punt) subpunt.proposalPoint = 1.1 subpunt.defaultContent = RichTextValue(getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output subpunt.estatsLlista = u'Esborrany' subacord = api.content.create(type='genweb.organs.acord', id='acord', title='Acord Exemple', container=punt) subacord.proposalPoint = '2' subacord.agreement = og_string + '/2018/01/02' subacord.defaultContent = RichTextValue(getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output subacord.estatsLlista = u'Esborrany' acord = api.content.create(type='genweb.organs.acord', id='acord', title='Acord Exemple', container=session_open) acord.proposalPoint = '2' acord.agreement = og_string + '/2018/01/01' acord.defaultContent = RichTextValue(getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output acord.estatsLlista = u'Esborrany' api.content.copy(source=document_public, target=acord, safe_id=True) api.content.copy(source=document_restringit, target=acord, safe_id=True) api.content.copy(source=document_both, target=acord, safe_id=True) api.content.copy(source=document_public, target=subpunt, safe_id=True) api.content.copy(source=document_restringit, target=subpunt, safe_id=True) api.content.copy(source=document_both, target=subpunt, safe_id=True) api.content.copy(source=document_public, target=subacord, safe_id=True) api.content.copy(source=document_restringit, target=subacord, safe_id=True) api.content.copy(source=document_both, target=subacord, safe_id=True) pdf_file = os.path.abspath( os.path.join(os.path.dirname(__file__), '..', 'tests')) + '/testfile.pdf' public_file = NamedBlobFile(data=open(pdf_file, 'r').read(), contentType='application/pdf', filename=u'pdf-public.pdf') restricted_file = NamedBlobFile(data=open(pdf_file, 'r').read(), contentType='application/pdf', filename=u'pdf-restringit.pdf') acta = api.content.create(type='genweb.organs.acta', id='acta', title='Acta Exemple', container=session_open) acta.llocConvocatoria = u'Barcelona' acta.enllacVideo = u'http://www.upc.edu' acta.ordenDelDia = RichTextValue(getLoremIpsum(2, 'long', 'html'), 'text/html', 'text/html').output acta.membresConvocats = acta.ordenDelDia acta.membresConvidats = acta.ordenDelDia acta.llistaExcusats = acta.ordenDelDia acta.llistaNoAssistens = acta.ordenDelDia acta.file = public_file acta.horaInici = session_open.start acta.horaFi = session_open.end acc.horaFi = tz.localize(datetime(2018, 11, 20, 10, 0)) audio = api.content.create(type='genweb.organs.audio', id='audio', title='Audio Exemple', container=acta) audio.description = u'audio mp3 description' mp3_file = os.path.abspath( os.path.join(os.path.dirname(__file__), '..', 'tests')) + '/testaudio.mp3' audio_file = NamedBlobFile(data=open(mp3_file, 'r').read(), contentType='audio/mpeg', filename=u'acta-audio.mp3') audio.file = audio_file filepunt_1 = api.content.create(type='genweb.organs.file', id='public', title='Fitxer NOMÉS Públic', container=punt) filepunt_1.visiblefile = public_file filepunt_2 = api.content.create(type='genweb.organs.file', id='restringit', title='Fitxer NOMÉS Restringit', container=punt) filepunt_2.hiddenfile = restricted_file filepunt_3 = api.content.create(type='genweb.organs.file', id='public-restringit', title='Fitxer Públic i Restringit', container=punt) filepunt_3.visiblefile = public_file filepunt_3.hiddenfile = restricted_file api.content.copy(source=filepunt_1, target=subpunt, safe_id=True) api.content.copy(source=filepunt_2, target=subpunt, safe_id=True) api.content.copy(source=filepunt_3, target=subpunt, safe_id=True) api.content.copy(source=filepunt_1, target=acord, safe_id=True) api.content.copy(source=filepunt_2, target=acord, safe_id=True) api.content.copy(source=filepunt_3, target=acord, safe_id=True) api.content.copy(source=filepunt_1, target=subacord, safe_id=True) api.content.copy(source=filepunt_2, target=subacord, safe_id=True) api.content.copy(source=filepunt_3, target=subacord, safe_id=True) sessio_convocada = api.content.copy(source=session_open, target=open_og, id='convocada') sessio_convocada.title = 'Sessió Convocada' api.content.transition(obj=sessio_convocada, transition='convocar') transaction.commit() sessio_realitzada = api.content.copy(source=sessio_convocada, target=open_og, id='realitzada') sessio_realitzada.title = 'Sessió Realitzada' api.content.transition(obj=sessio_realitzada, transition='convocar') api.content.transition(obj=sessio_realitzada, transition='realitzar') transaction.commit() sessio_tancada = api.content.copy(source=sessio_realitzada, target=open_og, id='tancada') sessio_tancada.title = 'Sessió Tancada' api.content.transition(obj=sessio_tancada, transition='convocar') api.content.transition(obj=sessio_tancada, transition='realitzar') api.content.transition(obj=sessio_tancada, transition='tancar') transaction.commit() sessio_modificada = api.content.copy(source=sessio_realitzada, target=open_og, id='correccio') sessio_modificada.title = 'Sessió en Correcció' api.content.transition(obj=sessio_modificada, transition='convocar') api.content.transition(obj=sessio_modificada, transition='realitzar') api.content.transition(obj=sessio_modificada, transition='tancar') api.content.transition(obj=sessio_modificada, transition='corregir') transaction.commit()
def migrate_typerestriction(self): constraints = ISelectableConstrainTypes(self.new) constraints.setConstrainTypesMode(ENABLED) constraints.setImmediatelyAddableTypes(self.new_allowed) constraints.setLocallyAllowedTypes(self.new_allowed)
def __init__(self, context): self.context = ISelectableConstrainTypes(context)
def __call__(self, context): constrain_aspect = ISelectableConstrainTypes(context) items = [] for type_ in constrain_aspect.getDefaultAddableTypes(): items.append(SimpleTerm(value=type_.getId(), title=type_.Title())) return SimpleVocabulary(items)
def eventoCreateHandler(evento, event): """ Complete content type evento setup on added event, generating missing folders, fields, etc. @param evento: Content item @param event: Event that triggers the method (onAdded event) """ if not IDesignPloneContenttypesLayer.providedBy(evento.REQUEST): return if "multimedia" not in evento.keys(): galleria = api.content.create( container=evento, type="Document", title="Multimedia", id="multimedia", ) create_default_blocks(context=galleria) # select constraints constraintsGalleria = ISelectableConstrainTypes(galleria) constraintsGalleria.setConstrainTypesMode(1) constraintsGalleria.setLocallyAllowedTypes(("Image", "Link")) with api.env.adopt_roles(["Reviewer"]): api.content.transition(obj=galleria, transition="publish") if "sponsor_evento" not in evento.keys(): sponsor = api.content.create( container=evento, type="Document", title="Sponsor Evento", id="sponsor_evento", ) create_default_blocks(context=sponsor) constraintsSponsor = ISelectableConstrainTypes(sponsor) constraintsSponsor.setConstrainTypesMode(1) constraintsSponsor.setLocallyAllowedTypes(("Link", )) with api.env.adopt_roles(["Reviewer"]): api.content.transition(obj=sponsor, transition="publish") if "documenti" not in evento.keys(): documenti = api.content.create( container=evento, type="Document", title="Documenti", id="documenti", ) create_default_blocks(context=documenti) constraintsDocumenti = ISelectableConstrainTypes(documenti) constraintsDocumenti.setConstrainTypesMode(1) constraintsDocumenti.setLocallyAllowedTypes(("File", )) with api.env.adopt_roles(["Reviewer"]): api.content.transition(obj=documenti, transition="publish")