def _cleanup_action_context(self, context_str, user_id): """Returns a dict representing the context_str evaluated (safe_eval) as a dict where items that are not useful for shared actions have been removed. If the evaluation of context_str as a dict fails, context_str is returned unaltered. :param user_id: the integer uid to be passed as 'uid' in the evaluation context """ result = False if context_str: try: context = safe_eval(context_str, tools.UnquoteEvalContext(), nocopy=True) result = dict(context) for key in context: # Remove all context keys that seem to toggle default # filters based on the current user, as it makes no sense # for shared users, who would not see any data by default. if key and key.startswith('search_default_') and 'user_id' in key: result.pop(key) except Exception: # Note: must catch all exceptions, as UnquoteEvalContext may cause many # different exceptions, as it shadows builtins. _logger.debug("Failed to cleanup action context as it does not parse server-side", exc_info=True) result = context_str return result
def get_needaction_data(self, cr, uid, ids, context=None): """ Return for each menu entry of ids : - if it uses the needaction mechanism (needaction_enabled) - the needaction counter of the related action, taking into account the action domain """ if context is None: context = {} res = {} menu_ids = set() for menu in self.browse(cr, uid, ids, context=context): menu_ids.add(menu.id) ctx = None if menu.action and menu.action.type in ( 'ir.actions.act_window', 'ir.actions.client') and menu.action.context: try: # use magical UnquoteEvalContext to ignore undefined client-side variables such as `active_id` eval_ctx = tools.UnquoteEvalContext(**context) ctx = eval(menu.action.context, locals_dict=eval_ctx, nocopy=True) or None except Exception: # if the eval still fails for some reason, we'll simply skip this menu pass menu_ref = ctx and ctx.get('needaction_menu_ref') if menu_ref: if not isinstance(menu_ref, list): menu_ref = [menu_ref] model_data_obj = self.pool.get('ir.model.data') for menu_data in menu_ref: model, id = model_data_obj.get_object_reference( cr, uid, menu_data.split('.')[0], menu_data.split('.')[1]) if (model == 'ir.ui.menu'): menu_ids.add(id) menu_ids = list(menu_ids) for menu in self.browse(cr, uid, menu_ids, context=context): res[menu.id] = { 'needaction_enabled': False, 'needaction_counter': False, } if menu.action and menu.action.type in ( 'ir.actions.act_window', 'ir.actions.client') and menu.action.res_model: obj = self.pool.get(menu.action.res_model) if obj and obj._needaction: if menu.action.type == 'ir.actions.act_window': dom = menu.action.domain and eval( menu.action.domain, {'uid': uid}) or [] else: dom = eval(menu.action.params_store or '{}', { 'uid': uid }).get('domain') res[menu.id]['needaction_enabled'] = obj._needaction res[menu.id]['needaction_counter'] = obj._needaction_count( cr, uid, dom, context=context) return res