def build_survey_tree(context, root): """Build a simple datastructure describing (part of) a survey. This implementation does a walk over the content itself. It is possible to also do this based on a catalog query, but since we use light-weight content items this should be simpler and removes the need to turn a catalog result back into a tree. :rtype: dict """ normalize = getUtility(IIDNormalizer).normalize tree = {'title': root.title, 'path': '/'.join(root.getPhysicalPath()), 'portal_type': normalize(root.portal_type), 'children': [], 'url': root.absolute_url(), } todo = collections.deque([(root, [], tree['children'])]) while todo: (node, index, child_list) = todo.popleft() for (ix, child) in enumerate(node.values(), 1): if not (IQuestionContainer.providedBy(child) or IRisk.providedBy(child)): continue child_index = index + [str(ix)] info = {'title': child.title, 'children': [], 'number': '.'.join(child_index), 'path': '/'.join(child.getPhysicalPath()), 'url': child.absolute_url(), 'disabled': not is_allowed(context, child), 'portal_type': normalize(child.portal_type), } child_list.append(info) todo.append((child, child_index, info['children'])) return tree
def buildExternalIdMap(self, root, zodb_path=[], mapping=None): if mapping is None: mapping = {} for child in root.values(): external_id = getattr(aq_base(child), "external_id", None) newpath = zodb_path + [child.id] if external_id is not None: mapping[external_id] = "/".join(newpath) if IQuestionContainer.providedBy(child): self.buildExternalIdMap(child, newpath, mapping) return mapping
def update(self): actions = getFactoriesInContext(self.context) if IModule.providedBy(self.context): for (i, action) in enumerate(actions): # To be able to determine what button label to display, we # explicitly set the action.id to the fake "euphorie.submodule" if action.id == "euphorie.module": actions[i] = FactoryInfo("euphorie.submodule", _(u"Submodule"), *action[2:]) break self.actions = sorted(actions, key=lambda x: x.title) self.can_edit = checkPermission(self.context, "Modify portal content") self.library_available = IQuestionContainer.providedBy(self.context)
def update(self): actions = getFactoriesInContext(self.context) if IModule.providedBy(self.context): for (i, action) in enumerate(actions): # To be able to determine what button label to display, we # explicitly set the action.id to the fake "euphorie.submodule" if action.id == "euphorie.module": actions[i] = FactoryInfo("euphorie.submodule", _("Submodule"), *action[2:]) break self.actions = sorted(actions, key=lambda x: x.title) self.can_edit = checkPermission(self.context, "Modify portal content") self.library_available = IQuestionContainer.providedBy(self.context)
def getSurveyTree(survey, profile=None): """Return a list of all modules, profile questions and risks in a survey. Each entry is represented by a dict with a `zodb_path` and `type` key. """ # XXX Can this be cached on the survey instance? nodes = [] base_length = len(survey.getPhysicalPath()) queue = collections.deque(survey.values()) while queue: node = queue.popleft() if node.portal_type not in [ "euphorie.profilequestion", "euphorie.module", "euphorie.risk", ]: continue # Note that in profile.AddToTree, we pretend that an optional module # always has a description. This logic needs to be replicated here. if node.portal_type == "euphorie.module": has_description = HasText(node.description) or node.optional else: has_description = HasText(node.description) if profile and node.portal_type == "euphorie.profilequestion": if not profile.get(node.id): continue nodes.append({ "zodb_path": "/".join(node.getPhysicalPath()[base_length:]), "type": node.portal_type[9:], "has_description": has_description, "always_present": (node.portal_type[9:] == "risk" and node.risk_always_present or False), "risk_type": (node.portal_type[9:] == "risk" and node.type or None), "optional": node.optional, }) if IQuestionContainer.providedBy(node): queue.extend(node.values()) return nodes
def getSurveyTree(survey): """Return a list of all modules, profile questions and risks in a survey. Each entry is represented by a dict with a `zodb_path` and `type` key. """ # XXX Can this be cached on the survey instance? nodes = [] base_length = len(survey.getPhysicalPath()) queue = collections.deque(survey.values()) while queue: node = queue.popleft() if node.portal_type not in \ ['euphorie.profilequestion', 'euphorie.module', 'euphorie.risk']: continue nodes.append({ 'zodb_path': '/'.join(node.getPhysicalPath()[base_length:]), 'type': node.portal_type[9:], 'has_description': HasText(node.description), 'optional': node.optional, }) if IQuestionContainer.providedBy(node): queue.extend(node.values()) return nodes
def getSurveyTree(survey): """Return a list of all modules, profile questions and risks in a survey. Each entry is represented by a dict with a `zodb_path` and `type` key. """ # XXX Can this be cached on the survey instance? nodes = [] base_length = len(survey.getPhysicalPath()) queue = collections.deque(survey.values()) while queue: node = queue.popleft() if node.portal_type not in \ ['euphorie.profilequestion', 'euphorie.module', 'euphorie.risk']: continue nodes.append({ 'zodb_path': '/'.join(node.getPhysicalPath()[base_length:]), 'type': node.portal_type[9:], 'has_description': HasText(node.description), 'always_present': node.portal_type[9:] == "risk" and node.risk_always_present or False, 'optional': node.optional, }) if IQuestionContainer.providedBy(node): queue.extend(node.values()) return nodes
def AddToTree(root, node, zodb_path=[], title=None, profile_index=0, skip_children=False): """Add a new node to the session tree. :param root: parent node of the new child :type root: py:class:`euphorie.client.model.SurveySession` or :py:class:`euphorie.client.model.SurveyTreeItem` :param node: ZODB object to add to the node. :type node: one of the :py:mod:`euphorie.content` content types :param zodb_path: list of ids of all parents of the root in the session tree :param title: title for the generated node. Defaults to the title of the ZODB object :type title: unicode or None :param int profile_index: profile answer index number. """ title = title or node.title if title: title = title[:500] if IQuestionContainer.providedBy(node): child = model.Module(title=title, module_id=node.id) child.has_description = HasText(node.description) if IModule.providedBy(node): child.solution_direction = HasText(node.solution_direction) if node.optional: child.skip_children = False child.has_description = True else: child.postponed = False elif IRisk.providedBy(node): priority = getattr(node, "default_priority", None) if priority == "none": priority = None if IFrenchRisk.providedBy(node): effect = node.default_severity else: effect = node.default_effect child = model.Risk(title=title, risk_id=node.id, risk_type=node.type, skip_evaluation=(node.evaluation_method == 'fixed'), probability=node.default_probability, frequency=node.default_frequency, effect=effect, priority=priority) child.skip_children = False child.postponed = False child.has_description = HasText(node.description) if node.type in ['top5', 'policy']: child.priority = 'high' if node.risk_always_present: child.identification = u"no" else: return None # Should never happen zodb_path = zodb_path + [node.id] child.zodb_path = "/".join(zodb_path) child.profile_index = profile_index root.addChild(child) if IQuestionContainer.providedBy(node) and not skip_children: for grandchild in node.values(): AddToTree(child, grandchild, zodb_path, None, profile_index) return child
def update(self): super(OshaAddBarTile, self).update() self.library_available = IQuestionContainer.providedBy(self.context)