def testMigrateStaticTextPortlets(self): class HiddenAssignment(static.Assignment): hide = True self.setRoles(["Manager"]) self.portal.invokeFactory('Folder', id="statictest") folder = self.portal['statictest'] manager = getUtility( IPortletManager, name='plone.rightcolumn', context=folder) assignments = getMultiAdapter( (folder, manager), IPortletAssignmentMapping) hidden_portlet = HiddenAssignment() visible_portlet = static.Assignment() assignments['hidden'] = hidden_portlet assignments['visible'] = visible_portlet migrateStaticTextPortlets(self.portal) self.assertFalse( IPortletAssignmentSettings(hidden_portlet).get( 'visible', True)) self.assertTrue( IPortletAssignmentSettings(visible_portlet).get( 'visible', True))
def test_portlet_visibility_settings(self): assignment = self.layer['right_portlets'].get('title2', False) settings = PersistentMapping({'visible': False}) IPortletAssignmentSettings(assignment).data = settings # get the data adapter = getAdapter(self.layer['folder1'], IDataCollector, name="portlet_data_adapter") data = adapter.getData() jsondata = json.dumps(utils.decode_for_json(data)) data = utils.encode_after_json(json.loads(jsondata)) self.assertEqual(settings, data['plone.rightcolumn']['title2']['settings']) # set the data adapter2 = getAdapter(self.layer['folder2'], IDataCollector, name="portlet_data_adapter") adapter2.setData(data, metadata=None) new_assignment = self.layer['right_portlets'].get('title2', False) self.assertEqual(settings, IPortletAssignmentSettings(new_assignment).data)
def testAssignmentSettings(self): mapping = assignment_mapping_from_key(self.portal, manager_name=u"test.testcolumn", category=CONTEXT_CATEGORY, key="/") assignment = mapping['test.portlet1'] settings = IPortletAssignmentSettings(assignment) self.assertTrue(settings.get('visible', True)) assignment = mapping['test.portlet2'] settings = IPortletAssignmentSettings(assignment) self.assertFalse(settings.get('visible', True))
def extract_mapping(manager_name, category, key, mapping): portlets_schemata = dict([ (iface, name) for name, iface in getUtilitiesFor(IPortletTypeInterface) ]) for name, assignment in mapping.items(): type_ = None schema = None for schema in providedBy(assignment).flattened(): type_ = portlets_schemata.get(schema, None) if type_ is not None: break if type_ is not None: child = PrettyDocument().createElement('assignment') child.setAttribute('manager', manager_name) child.setAttribute('category', category) child.setAttribute('key', key) child.setAttribute('type', type_) child.setAttribute('name', name) assignment = assignment.__of__(mapping) settings = IPortletAssignmentSettings(assignment) visible = settings.get('visible', True) child.setAttribute('visible', repr(visible)) handler = IPortletAssignmentExportImportHandler(assignment) handler.export_assignment(schema, PrettyDocument(), child) yield child
def extractMapping(manager_name, category, key, mapping): for name, assignment in mapping.items(): type_ = None for schema in providedBy(assignment).flattened(): type_ = portletSchemata.get(schema, None) if type_ is not None: break if type_ is not None: child = self._doc.createElement('assignment') child.setAttribute('manager', manager_name) child.setAttribute('category', category) child.setAttribute('key', key) child.setAttribute('type', type_) child.setAttribute('name', name) assignment = assignment.__of__(mapping) settings = IPortletAssignmentSettings(assignment) visible = settings.get('visible', True) child.setAttribute('visible', repr(visible)) handler = IPortletAssignmentExportImportHandler(assignment) handler.export_assignment(schema, self._doc, child) fragment.appendChild(child)
def getPortlets(self): if IPortletContext.providedBy(self.context): pcontext = self.context else: pcontext = queryAdapter(self.context, IPortletContext) if pcontext is None: return [] assignments = [] for category, key in pcontext.globalPortletCategories(True): mapping = self.storage.get(category, None) if mapping is not None: for assignment in mapping.get(key, {}).values(): try: settings = IPortletAssignmentSettings(assignment) except TypeError: # Portlet does not exist any longer continue else: if not settings.get('visible', True): continue assignments.append({'category': category, 'key': key, 'name': assignment.__name__, 'assignment': assignment }) return assignments
def toggle_visibility(self, name): self.authorize() assignments = aq_inner(self.context) settings = IPortletAssignmentSettings(assignments[name]) visible = settings.get('visible', True) settings['visible'] = not visible return self.finish_portlet_change()
def global_portlets(self, category, prefix): """ Return the list of global portlets from a given category for the current context. Invisible (hidden) portlets are excluded. """ context = aq_inner(self.context) # get the portlet context pcontext = IPortletContext(self.context) portal_state = getMultiAdapter((context, self.request), name=u'plone_portal_state') # noqa base_url = portal_state.portal_url() portlets = [] for cat, key in pcontext.globalPortletCategories(False): if cat == category: mapping = self.manager.get(category, None) assignments = [] if mapping is not None: is_visible = lambda a: IPortletAssignmentSettings(a).get( 'visible', True) # noqa assignments.extend([ a for a in mapping.get(key, {}).values() if is_visible(a) ]) if assignments: edit_url = '%s/++%s++%s+%s' % (base_url, prefix, self.manager.__name__, key) portlets.extend( self.portlets_for_assignments(assignments, self.manager, edit_url)) return portlets
def _lazyLoadPortlets(self, manager): retriever = getMultiAdapter((self.context, manager), IPortletRetriever) items = [] for p in self.filter(retriever.getPortlets()): renderer = self._dataToPortlet(p['assignment'].data) info = p.copy() info['manager'] = self.manager.__name__ info['renderer'] = renderer hashPortletInfo(info) # Record metadata on the renderer renderer.__portlet_metadata__ = info.copy() del renderer.__portlet_metadata__['renderer'] try: isAvailable = renderer.available except ConflictError: raise except Exception, e: isAvailable = False logger.exception( "Error while determining renderer availability of portlet " "(%r %r %r): %s" % (p['category'], p['key'], p['name'], str(e))) info['available'] = isAvailable assignments = info['assignment'].__parent__ settings = IPortletAssignmentSettings(assignments[info['name']]) info['settings'] = settings items.append(info)
def test_invoke_edit_form(self): mapping = PortletAssignmentMapping() request = self.folder.REQUEST mapping['foo'] = news.Assignment(count=5) editview = getMultiAdapter((mapping['foo'], request), name='edit') editview.update() editview.applyChanges(data={ 'count': 6, EXTENDER_PREFIX + '.css_class': 'my-class' }) portlet_assignment = mapping.values()[0] settings = IPortletAssignmentSettings(portlet_assignment) self.assertEqual(portlet_assignment.count, 6) # We have not extended our storage adapter, so nothing gets saved: self.assertIsNone(settings.get('css_class', None)) # Register our schemaextender gsm = getGlobalSiteManager() gsm.registerAdapter(PortletCssClassAdapter, (IPortletAssignment, )) gsm.registerAdapter( PortletCssClassFormExtender, (Interface, IDefaultBrowserLayer, IPortletEditForm), IFormExtender, 'portletcssclass.extender') mapping = PortletAssignmentMapping() request = self.folder.REQUEST mapping['foo'] = news.Assignment(count=5) editview = getMultiAdapter((mapping['foo'], request), name='edit') editview.update() editview.applyChanges(data={ 'count': 6, EXTENDER_PREFIX + '.css_class': 'my-class' }) portlet_assignment = mapping.values()[0] settings = IPortletAssignmentSettings(portlet_assignment) gsm.unregisterAdapter( PortletCssClassFormExtender, (Interface, IDefaultBrowserLayer, IPortletEditForm), IFormExtender, 'portletcssclass.extender') gsm.unregisterAdapter(PortletCssClassAdapter, (IPortletAssignment, )) self.assertEqual(portlet_assignment.count, 6) # The prefix is used for the form field, not for the stored data: self.assertEqual(settings.get('css_class'), 'my-class')
def test_invoke_add_form(self): portlet = getUtility(IPortletType, name='portlets.News') mapping = self.portal.restrictedTraverse( '++contextportlets++plone.leftcolumn') for m in mapping.keys(): del mapping[m] addview = mapping.restrictedTraverse('+/' + portlet.addview) addview.update() addview.createAndAdd(data={ 'count': 5, EXTENDER_PREFIX + '.css_class': 'my-class' }) portlet_assignment = mapping.values()[0] settings = IPortletAssignmentSettings(portlet_assignment) self.assertEqual(portlet_assignment.count, 5) # We have not extended our storage adapter, so nothing gets saved: self.assertIsNone(settings.get('css_class', None)) # Register our schemaextender gsm = getGlobalSiteManager() gsm.registerAdapter(PortletCssClassAdapter, (IPortletAssignment, )) gsm.registerAdapter(PortletCssClassFormExtender, (Interface, IDefaultBrowserLayer, IPortletAddForm), IFormExtender, 'portletcssclass.extender') for m in mapping.keys(): del mapping[m] addview = mapping.restrictedTraverse('+/' + portlet.addview) addview.update() addview.createAndAdd(data={ 'count': 5, EXTENDER_PREFIX + '.css_class': 'my-class' }) portlet_assignment = mapping.values()[0] settings = IPortletAssignmentSettings(portlet_assignment) gsm.unregisterAdapter( PortletCssClassFormExtender, (Interface, IDefaultBrowserLayer, IPortletAddForm), IFormExtender, 'portletcssclass.extender') gsm.unregisterAdapter(PortletCssClassAdapter, (IPortletAssignment, )) self.assertEqual(portlet_assignment.count, 5) # The prefix is used for the form field, not for the stored data: self.assertEqual(settings.get('css_class'), 'my-class')
def panels_for_assignments(self, assignments, manager, base_url): # todo: do we use a special cat for panels? category = self.__parent__.category key = self.__parent__.key data = [] for idx in range(len(assignments)): name = assignments[idx].__name__ if hasattr(assignments[idx], '__Broken_state__'): name = assignments[idx].__Broken_state__['__name__'] # Todo: we can define an edit view for panels - for overlay etc. - IF needed... editview = queryMultiAdapter((assignments[idx], self.request), name='edit', default=None) if editview is None: editviewName = '' else: editviewName = '%s/%s/edit' % (base_url, name) panel_hash = hashPortletInfo( dict( manager=manager.__name__, category=category, key=key, name=name, )) try: settings = IPortletAssignmentSettings(assignments[idx]) visible = settings.get('visible', True) except TypeError: visible = False data.append({ 'title': assignments[idx].title, 'editview': editviewName, 'hash': panel_hash, 'name': name, 'up_url': '%s/@@move-panel-up' % (base_url), 'down_url': '%s/@@move-panel-down' % (base_url), 'delete_url': '%s/@@delete-panel' % (base_url), 'duplicate_url': '%s/@@duplicate-panel' % (base_url), 'hide_url': '%s/@@toggle-visibility' % (base_url), 'show_url': '%s/@@toggle-visibility' % (base_url), 'visible': visible, 'has_assignments': len(assignments[idx]), }) if len(data) > 0: data[0]['up_url'] = data[-1]['down_url'] = None return data
def portlets_for_assignments(self, assignments, manager, base_url): category = self.__parent__.category key = self.__parent__.key data = [] for idx in range(len(assignments)): name = assignments[idx].__name__ if hasattr(assignments[idx], '__Broken_state__'): name = assignments[idx].__Broken_state__['__name__'] editview = queryMultiAdapter((assignments[idx], self.request), name='edit', default=None) if editview is None: editviewName = '' else: editviewName = '%s/%s/edit' % (base_url, name) settingsviewName = '%s/%s/edit-portlet-metadata' % (base_url, name) portlet_hash = hashPortletInfo( dict( manager=manager.__name__, category=category, key=key, name=name, )) try: settings = IPortletAssignmentSettings(assignments[idx]) visible = settings.get('visible', True) except TypeError: visible = False data.append({ 'title': assignments[idx].title, 'editview': editviewName, 'hash': portlet_hash, 'name': name, 'up_url': '%s/@@move-portlet-up' % base_url, 'down_url': '%s/@@move-portlet-down' % base_url, 'delete_url': '%s/@@delete-portlet' % base_url, 'metadata_url': settingsviewName, 'hide_url': '%s/@@toggle-visibility' % base_url, 'show_url': '%s/@@toggle-visibility' % base_url, 'visible': visible, }) if len(data) > 0: data[0]['up_url'] = data[-1]['down_url'] = None return data
def __call__(self): # The parent object is the Plone content object here; we get # it from the acquisition chain. parent = self.context.aq_inner.aq_parent.aq_parent panel = self.context portlets = [] for assignment in panel: settings = IPortletAssignmentSettings(assignment) if not settings.get('visible', True): continue try: portlet = getMultiAdapter( (parent, self.request, self, panel, assignment), IPortletRenderer) except ComponentLookupError: logging.getLogger("panels").info( "unable to look up renderer for '%s.%s'." % (assignment.__class__.__module__, assignment.__class__.__name__)) continue info = { 'manager': "panels", 'category': CONTEXT_CATEGORY, 'key': '/'.join(panel.getPhysicalPath()), 'name': assignment.__name__, 'renderer': portlet, 'settings': settings, 'assignment': assignment } hashPortletInfo(info) portlet.update() try: available = portlet.available except Exception as e: logging.getLogger('panels').info( "available threw an exception for %s (%s %s)" % (assignment.__name__, type(e), str(e))) continue if available: result = self.portlet(**info) portlets.append(result) return render(portlets, self.context.layout, self.request)
def migrate_portlets_for_object(obj, path): portlet_managers = getUtilitiesFor(IPortletManager, context=obj) for portlet_manager_name, portlet_manager in portlet_managers: assignments = queryMultiAdapter( (obj, portlet_manager), IPortletAssignmentMapping, context=obj) if assignments is None: continue for portlet_id, portlet in assignments.items(): if IStaticPortlet.providedBy(portlet) and \ getattr(portlet, 'hide', False): logger.info( 'Found hidden static text portlet %s at %s' % (portlet_id, path)) settings = IPortletAssignmentSettings(portlet) settings['visible'] = False
def export_local_portlets(obj): """Serialize portlets for one content object Code mostly taken from https://github.com/plone/plone.restapi/pull/669 """ portlets_schemata = { iface: name for name, iface in getUtilitiesFor(IPortletTypeInterface) } items = {} for manager_name, manager in getUtilitiesFor(IPortletManager): mapping = queryMultiAdapter((obj, manager), IPortletAssignmentMapping) if mapping is None: continue mapping = mapping.__of__(obj) for name, assignment in mapping.items(): portlet_type = None schema = None for schema in providedBy(assignment).flattened(): portlet_type = portlets_schemata.get(schema, None) if portlet_type is not None: break if portlet_type is None: continue assignment = assignment.__of__(mapping) settings = IPortletAssignmentSettings(assignment) if manager_name not in items: items[manager_name] = [] values = {} for name in schema.names(): value = getattr(assignment, name, None) if RelationValue is not None and isinstance( value, RelationValue): value = value.to_object.UID() elif isinstance(value, RichTextValue): value = { "data": json_compatible(value.raw), "content-type": json_compatible(value.mimeType), "encoding": json_compatible(value.encoding), } value = json_compatible(value) values[name] = value items[manager_name].append({ "type": portlet_type, "visible": settings.get("visible", True), "assignment": values, }) return items
def getPortlets(self): """Work out which portlets to display, returning a list of dicts describing assignments to render. """ manager = self.storage.__name__ pcontext = IPortletContext(self.context, None) if pcontext is None: return [] assignable = ILocalPortletAssignable(self.context, None) if assignable is None: return [] annotations = IAnnotations(assignable, None) if annotations is None: return [] local = annotations.get(CONTEXT_ASSIGNMENT_KEY, None) if local is None: return [] localManager = local.get(manager, None) if localManager is None: return [] assignments = [] for assignment in localManager.values(): try: settings = IPortletAssignmentSettings(assignment) except TypeError: # Portlet does not exist any longer continue if not settings.get('visible', True): continue assignments.append(assignment) return [{ 'category': CONTEXT_CATEGORY, 'key': pcontext.uid, 'name': a.__name__, 'assignment': a } for a in assignments]
def get_portlets(self): portlets_schemata = { iface: name for name, iface in getUtilitiesFor(IPortletTypeInterface) } portlets = {} for manager_name, manager in getUtilitiesFor(IPortletManager): mapping = queryMultiAdapter( (self.context, manager), IPortletAssignmentMapping ) if mapping is None: continue mapping = mapping.__of__(self.context) for name, assignment in mapping.items(): type_ = None schema = None for schema in providedBy(assignment).flattened(): type_ = portlets_schemata.get(schema, None) if type_ is not None: break if type_ is None: continue assignment = assignment.__of__(mapping) settings = IPortletAssignmentSettings(assignment) if manager_name not in portlets: portlets[manager_name] = [] title = getattr(assignment, "title", "") or getattr( assignment, "header", "" ) portlets[manager_name].append( { "type": type_, "title": title, "visible": settings.get("visible", True), "assignment": { name: getattr(assignment, name, None) for name in schema.names() }, } ) self["portlets"] = portlets
def exportAssignments(self, obj): assignments = [] for manager_name, manager in self.portlet_managers: mapping = queryMultiAdapter((obj, manager), IPortletAssignmentMapping) if mapping is None: continue mapping = mapping.__of__(obj) if len(mapping.items()) > 0: for name, assignment in mapping.items(): type_ = None for schema in providedBy(assignment).flattened(): type_ = self.portlet_schemata.get(schema, None) if type_ is not None: break if type_ is not None: child = self.doc.createElement('assignment') child.setAttribute('manager', manager_name) child.setAttribute('category', CONTEXT_CATEGORY) child.setAttribute('key', '/'.join(obj.getPhysicalPath())) child.setAttribute('type', type_) child.setAttribute('name', name) settings = IPortletAssignmentSettings(assignment) if not settings.get('visible', True): child.setAttribute('visible', 'False') assignment = assignment.__of__(mapping) # use existing adapter for exporting a portlet assignment # noqa handler = IPortletAssignmentExportImportHandler( assignment) # noqa handler.export_assignment(schema, self.doc, child) assignments.append(child) return assignments
def _initAssignmentNode(self, node): """Create an assignment from a node """ site = self.environ.getSite() # 1. Determine the assignment mapping and the name manager = node.getAttribute('manager') category = node.getAttribute('category') key = node.getAttribute('key') # convert unicode to str as unicode paths are not allowed in # restrictedTraverse called in assignment_mapping_from_key if six.PY2: key = key.encode() purge = False if node.hasAttribute('purge'): purge = self._convertToBoolean(node.getAttribute('purge')) mapping = assignment_mapping_from_key(site, manager, category, key, create=True) # 2. Either find or create the assignment assignment = None name = node.getAttribute('name') if name: name = str(name) assignment = mapping.get(name, None) __traceback_info__ = "Assignment name: " + name if node.hasAttribute('remove'): if assignment is not None: del mapping[name] return if purge: for portlet in mapping.keys(): del mapping[portlet] return type_ = str(node.getAttribute('type')) if assignment is None: portlet_factory = getUtility(IFactory, name=type_) assignment = portlet_factory() if not name: chooser = INameChooser(mapping) name = chooser.chooseName(None, assignment) mapping[name] = assignment # aq-wrap it so that complex fields will work assignment = assignment.__of__(site) # set visibility setting visible = node.getAttribute('visible') if visible: settings = IPortletAssignmentSettings(assignment) settings['visible'] = self._convertToBoolean(visible) # 3. Use an adapter to update the portlet settings portlet_interface = getUtility(IPortletTypeInterface, name=type_) assignment_handler = IPortletAssignmentExportImportHandler(assignment) assignment_handler.import_assignment(portlet_interface, node) # 4. Handle ordering insert_before = node.getAttribute('insert-before') if insert_before: position = None keys = list(mapping.keys()) if insert_before == "*": position = 0 elif insert_before in keys: position = keys.index(insert_before) if position is not None: keys.remove(name) keys.insert(position, name) mapping.updateOrder(keys)
def register_portlets(obj, item): """Register portlets fror one object Code adapted from plone.app.portlets.exportimport.portlets.PortletsXMLAdapter Work in progress... """ site = api.portal.get() request = getRequest() results = 0 for manager_name, portlets in item.get("portlets", {}).items(): manager = getUtility(IPortletManager, manager_name) mapping = queryMultiAdapter((obj, manager), IPortletAssignmentMapping) namechooser = INameChooser(mapping) for portlet_data in portlets: # 1. Create the assignment assignment_data = portlet_data["assignment"] portlet_type = portlet_data["type"] portlet_factory = getUtility(IFactory, name=portlet_type) assignment = portlet_factory() name = namechooser.chooseName(None, assignment) mapping[name] = assignment logger.info("Added portlet {} to {}".format( name, obj.absolute_url())) # aq-wrap it so that complex fields will work assignment = assignment.__of__(site) # set visibility setting visible = portlet_data.get("visible") if visible: settings = IPortletAssignmentSettings(assignment) settings["visible"] = visible # 2. Apply portlet settings portlet_interface = getUtility(IPortletTypeInterface, name=portlet_type) for property_name, value in assignment_data.items(): field = portlet_interface.get(property_name, None) if field is None: continue field = field.bind(assignment) # deserialize data (e.g. for RichText) deserializer = queryMultiAdapter((field, obj, request), IFieldDeserializer) if deserializer is not None: try: value = deserializer(value) except Exception as e: logger.info( u"Could not import portlet data {} for field {} on {}: {}" .format(value, field, obj.absolute_url(), str(e))) continue field.set(assignment, value) results += 1 for blacklist_status in item.get("blacklist_status", []): status = blacklist_status["status"] manager_name = blacklist_status["manager"] category = blacklist_status["category"] manager = getUtility(IPortletManager, manager_name) assignable = queryMultiAdapter((obj, manager), ILocalPortletAssignmentManager) if status.lower() == "block": assignable.setBlacklistStatus(category, True) elif status.lower() == "show": assignable.setBlacklistStatus(category, False) return results
def setData(self, portletsdata, metadata): """create or updates portlet informations """ for manager_name in portletsdata.keys(): column = queryUtility(IPortletManager, name=manager_name, context=self.object) if column is None: continue # ok we have a portlet manager # get all current assigned portlets portlets = getMultiAdapter(( self.object, column, ), IPortletAssignmentMapping, context=self.object) p_ids = [p for p in portlets._data.keys()] # get new order order = portletsdata[manager_name]['order'] and \ portletsdata[manager_name]['order'].split(',') or [] # set blackliststatus blacklist = getMultiAdapter((self.object, column), ILocalPortletAssignmentManager) blacklistdata = portletsdata[manager_name]['blackliststatus'] blacklist.setBlacklistStatus(GROUP_CATEGORY, blacklistdata[GROUP_CATEGORY]) blacklist.setBlacklistStatus(USER_CATEGORY, blacklistdata[USER_CATEGORY]) blacklist.setBlacklistStatus(CONTENT_TYPE_CATEGORY, blacklistdata[CONTENT_TYPE_CATEGORY]) blacklist.setBlacklistStatus(CONTEXT_CATEGORY, blacklistdata[CONTEXT_CATEGORY]) # bit clean up del portletsdata[manager_name]['blackliststatus'] del portletsdata[manager_name]['order'] # remove all currenlty assigned portlets from manager for p_id in p_ids: del portlets._data[p_id] for portlet_id in portletsdata[manager_name].keys(): portletfielddata = portletsdata[manager_name][portlet_id] # get Assignment portlet_module = modules[portletfielddata['module']] portlet_class = getattr( portlet_module, portletfielddata['assignment_class_name']) settings = portletfielddata.get('settings', None) # prepare data to pass as arguments del portletfielddata['module'] del portletfielddata['assignment_class_name'] del portletfielddata['settings'] annotations = portletfielddata.get('__annotations__', None) if '__annotations__' in portletfielddata: del portletfielddata['__annotations__'] # check for dicts for k, v in portletfielddata.items(): if isinstance(v, dict): # so we have one, now we have to turn the # serialized data into an object # this is generic, but currently only in use # by the image portlet klass = modules[v['module']].__dict__[v['klass_name']] for argname in ('file', 'data'): if argname in v['kwargs']: v['kwargs'][argname] = base64.decodestring( v['kwargs'][argname]) imgobj = klass(**v['kwargs']) portletfielddata[k] = imgobj portlets[portlet_id] = portlet_class(**portletfielddata) # XXX boolean value fix # for some reason boolean types cannpt be passed with **... # use setattr for k, v in portletfielddata.items(): if isinstance(v, bool): setattr(portlets[portlet_id], k, v) if annotations: portlets[portlet_id].__annotations__ = annotations # portlet settings (visibility) portlet_assignment = portlets[portlet_id] IPortletAssignmentSettings(portlet_assignment).data = settings # set new order afterwards portlets._order = PersistentList(order)
def hidePortlet(context, portletName, columnName='plone.leftcolumn'): manager = getUtility(IPortletManager, columnName) assignmentMapping = getMultiAdapter((context, manager), IPortletAssignmentMapping) settings = IPortletAssignmentSettings(assignmentMapping[portletName]) settings['visible'] = False
def __setattr__(self, attr, value): settings = IPortletAssignmentSettings(self.context) settings[attr] = value
def __getattr__(self, attr): settings = IPortletAssignmentSettings(self.context) return settings.get(attr, None)
def is_visible(a): try: return IPortletAssignmentSettings(a).get('visible', True) except TypeError: # Assignment is broken return False
def getData(self): """returns all important data data form {'column': {portlet: {key:value} } . . . . {'blackliststatus': {category:True}, {'order': ['portlet 1', 'portlet 2']} } } """ data = {} plone_portlet_manager = [] # gets all portlet managers used on this object annotations = getattr(self.object, '__annotations__', None) if not annotations: return data has_portlets = 'plone.portlets.contextassignments' in annotations has_blacklist = 'plone.portlets.categoryblackliststatus' in annotations if not has_portlets and not has_blacklist: return data if has_portlets: plone_portlet_manager += self.object.__annotations__[ 'plone.portlets.contextassignments'].keys() if has_blacklist: plone_portlet_manager += self.object.__annotations__[ 'plone.portlets.categoryblackliststatus'].keys() EXCLUDED_FIELDS = ['__name__', '__parent__'] # XXX this is a static list, replace by a configlet option # the list contains all not serializable portlets (__module__) blacklisted_portlets = [ 'collective.dancing.browser.portlets.channelsubscribe' ] for manager_name in plone_portlet_manager: column = queryUtility(IPortletManager, name=manager_name, context=self.object) if column is None: continue # ok we have a portlet manager data[manager_name] = {} # get blackliststatus blacklist = getMultiAdapter((self.object, column), ILocalPortletAssignmentManager) data[manager_name]['blackliststatus'] = {} blacklistdata = data[manager_name]['blackliststatus'] blacklistdata[GROUP_CATEGORY] = blacklist.getBlacklistStatus( GROUP_CATEGORY) blacklistdata[USER_CATEGORY] = blacklist.getBlacklistStatus( USER_CATEGORY) blacklistdata[CONTENT_TYPE_CATEGORY] = \ blacklist.getBlacklistStatus(CONTENT_TYPE_CATEGORY) blacklistdata[CONTEXT_CATEGORY] = \ blacklist.getBlacklistStatus(CONTEXT_CATEGORY) portlets = getMultiAdapter(( self.object, column, ), IPortletAssignmentMapping, context=self.object) # portlets order - dicts are unsorted data[manager_name]['order'] = ','.join(portlets._order) for portlet_id in portlets.keys(): portlet_assignment = portlets[portlet_id] # continue if portlet is blacklisted if portlet_assignment.__module__ in blacklisted_portlets: continue # we habe a portlet data[manager_name][portlet_assignment.__name__] = {} data[manager_name][portlet_assignment.__name__]['module'] = \ portlet_assignment.__class__.__module__ data[manager_name][portlet_assignment.__name__]['assignment_class_name'] = \ portlet_assignment.__class__.__name__ # portlet settings (visibility) settings = IPortletAssignmentSettings(portlet_assignment).data data[manager_name][ portlet_assignment.__name__]['settings'] = settings # get all data for field in portlet_assignment.__dict__.keys(): if field not in EXCLUDED_FIELDS: field_value = getattr(portlet_assignment, field, '') # image field - image.portlet integration if isinstance(field_value, OFSImage): # same way as in AT field serializer field_value = { 'module': OFSImage.__module__, 'klass_name': OFSImage.__name__, 'kwargs': { 'file': base64.encodestring(field_value.data), 'id': field_value.id(), 'title': field_value.title } } elif (HAS_NAMEDFILE and INamedFile.providedBy(field_value)): klass = type(field_value) field_value = { 'module': klass.__module__, 'klass_name': klass.__name__, 'kwargs': { 'data': base64.encodestring(field_value.data), 'filename': field_value.filename, 'contentType': field_value.contentType } } data[manager_name][ portlet_assignment.__name__][field] = field_value return data
def __init__(self, context, request): super(DisplayPanelView, self).__init__(context, request) # todo: move away from init # The parent object is the Plone content object here; we get # it from the acquisition chain. # The panel can be rendered in different contexts, where the length of # the chain to the Plone content object is not obvious; # on portlet edit forms for instance, where we have a panel of # portlets below the edit form. # So to get the content object we go up in the aq chain, until we are # out of the chain of portlet assignments, panels etc. parent = self.context.aq_inner while True: parent = parent.aq_parent if not (IPanel.providedBy(parent) or IPortletAssignment.providedBy(parent) or IPortletAssignmentMapping.providedBy(parent)): break panel = self.context portlets = [] for assignment in panel: settings = IPortletAssignmentSettings(assignment) if not settings.get('visible', True): continue try: portlet = getMultiAdapter((parent, self.request, self, panel, assignment.__of__(panel)), IPortletRenderer) except ComponentLookupError: logging.getLogger("panels").info( "unable to look up renderer for '%s.%s'." % (assignment.__class__.__module__, assignment.__class__.__name__)) continue info = { 'manager': "panels", 'category': CONTEXT_CATEGORY, 'key': str('/'.join(parent.getPhysicalPath())), 'name': assignment.__name__, 'renderer': portlet, 'settings': settings, 'assignment': assignment } # todo: check new impl. of portlet rendering hashPortletInfo(info) portlet.__portlet_metadata__ = info.copy() del portlet.__portlet_metadata__['renderer'] portlet.update() try: available = portlet.available except ConflictError: raise except Exception as err: logging.getLogger('panels').info( "available threw an exception for %s (%s %s)" % (assignment.__name__, type(err), str(err))) continue info['available'] = available portlets.append(info) self.portlets = portlets
def getPortlets(self): """Work out which portlets to display, returning a list of dicts describing assignments to render. """ if IPortletContext.providedBy(self.context): pcontext = self.context else: pcontext = queryAdapter(self.context, IPortletContext) if pcontext is None: return [] # Holds a list of (category, key, assignment). categories = [] # Keeps track of the blacklisting status for global categores # (user, group, content type). The status is either True (blocked) # or False (not blocked). blacklisted = {} # This is the name of the manager (column) we're rendering manager = self.storage.__name__ # 1. Fetch blacklisting status for each global category # First, find out which categories we will need to determine # blacklist status for for category, key in pcontext.globalPortletCategories(False): blacklisted[category] = None # Then walk the content hierarchy to find out what blacklist status # was assigned. Note that the blacklist is tri-state; if it's None it # means no assertion has been made (i.e. the category has neither been # whitelisted or blacklisted by this object or any parent). The first # item to give either a blacklisted (True) or whitelisted (False) # value for a given item will set the appropriate value. Parents of # this item that also set a black- or white-list value will then be # ignored. # Whilst walking the hierarchy, we also collect parent portlets, # until we hit the first block. current = self.context currentpc = pcontext blacklistFetched = set() parentsBlocked = False while current is not None and currentpc is not None: if ILocalPortletAssignable.providedBy(current): assignable = current else: assignable = queryAdapter(current, ILocalPortletAssignable) if assignable is not None: if IAnnotations.providedBy(assignable): annotations = assignable else: annotations = queryAdapter(assignable, IAnnotations) if not parentsBlocked: local = annotations.get(CONTEXT_ASSIGNMENT_KEY, None) if local is not None: localManager = local.get(manager, None) if localManager is not None: categories.extend([(CONTEXT_CATEGORY, currentpc.uid, a) for a in localManager.values()]) lpam = getMultiAdapter((assignable, self.storage), ILocalPortletAssignmentManager) if lpam.getBlacklistStatus(CONTEXT_CATEGORY): parentsBlocked = True for cat, cat_status in blacklisted.items(): local_status = lpam.getBlacklistStatus(cat) if local_status is not None: blacklistFetched.add(cat) if cat_status is None: blacklisted[cat] = local_status # We can abort if parents are blocked and we've fetched all # blacklist statuses if parentsBlocked and len(blacklistFetched) == len(blacklisted): break # Check the parent - if there is no parent, we will stop current = currentpc.getParent() if current is not None: if IPortletContext.providedBy(current): currentpc = current else: currentpc = queryAdapter(current, IPortletContext) # Get all global mappings for non-blacklisted categories for category, key in pcontext.globalPortletCategories(False): if not blacklisted[category]: mapping = self.storage.get(category, None) if mapping is not None: for a in mapping.get(key, {}).values(): categories.append((category, key, a, )) assignments = [] for category, key, assignment in categories: try: settings = IPortletAssignmentSettings(assignment) if not settings.get('visible', True): continue except TypeError: # Portlet does not exist any longer continue assignments.append({'category': category, 'key': key, 'name': str(assignment.__name__), 'assignment': assignment }) return assignments
def create_portlet(self, data): errors = [] portlet_type = data.get('@type', None) iface = self.portlettypes.get(portlet_type) fields = getFields(iface) portlet_data = dict() for field_name, field in fields.items(): # Deserialize to field value deserializer = queryMultiAdapter((field, self.request), IFieldDeserializer) if deserializer is None or field_name not in data: continue try: value = deserializer(data[field_name]) except ValueError as e: errors.append({ "message": str(e), "field": field_name, "error": e }) continue except ValidationError as e: errors.append({ "message": e.doc(), "field": field_name, "error": e }) continue portlet_data[field_name] = value manager = queryMultiAdapter((self.context, self.manager), IPortletAssignmentMapping) factory = queryUtility(IFactory, name=portlet_type) if not factory: self.request.response.setStatus(501) return dict(error=dict( message="Could not get factory for portlet type {}".format( portlet_type))) assignment = factory(**portlet_data) portlet_id = data.get('portlet_id', None) if portlet_id: # If portlet id is specified, check if there is a portlet with that id, and if so, remove it if portlet_id in manager: # set fixing_up to True to let zope.container.contained # know that our object doesn't have __name__ and __parent__ fixing_up = contained.fixing_up contained.fixing_up = True del manager[portlet_id] # revert our fixing_up customization contained.fixing_up = fixing_up else: chooser = INameChooser(manager) portlet_id = chooser.chooseName(None, assignment) manager[portlet_id] = assignment visible = data.get('visible', True) settings = IPortletAssignmentSettings(assignment) settings['visible'] = visible