def exportModule(self, parent, module): """:returns: An XML node with the details of an :obj:`euphorie.content.module`.""" node = etree.SubElement( parent, "module", optional="true" if module.optional else "false") if getattr(module, "external_id", None): node.attrib["external-id"] = module.external_id etree.SubElement(node, "title").text = module.title if self.include_module_description_texts and HasText( module.description): node = self._add_string_or_html(node, module.description, "description") if module.optional: etree.SubElement(node, "question").text = module.question if self.include_module_solution_texts and StripMarkup( module.solution_direction): etree.SubElement(node, "solution-direction").text = StripUnwanted( module.solution_direction) if module.image is not None: self.exportImage(node, module.image, module.caption) for child in module.values(): if IModule.providedBy(child): self.exportModule(node, child) elif IRisk.providedBy(child): self.exportRisk(node, child) return node
def walk(node): for idx, sub_node in node.ZopeFind(node, search_sub=0): if IRisk.providedBy(sub_node): yield sub_node if IDexterityContainer.providedBy(sub_node): for sub_sub_node in walk(sub_node): yield sub_sub_node
def exportProfileQuestion(self, parent, profile): """:returns: An XML node with the details of an :obj:`euphorie.content.profilequestion`. """ node = etree.SubElement(parent, "profile-question") if getattr(profile, "external_id", None): node.attrib["external-id"] = profile.external_id etree.SubElement(node, "title").text = profile.title # Use title if question is not available (Euphorie < 2.0rc2 data) if HasText(profile.question): node = self._add_string_or_html(node, profile.question, "question") else: etree.SubElement(node, "question").text = profile.title if HasText(profile.description): node = self._add_string_or_html(node, profile.description, "description") for fname in ProfileQuestionLocationFields: value = getattr(profile, fname, None) if value: etree.SubElement(node, fname.replace("_", "-")).text = value etree.SubElement( node, "use-location-question").text = ("true" if getattr( profile, "use_location_question", True) else "false") for child in profile.values(): if IModule.providedBy(child): self.exportModule(node, child) elif IRisk.providedBy(child): self.exportRisk(node, child) return node
def exportModule(self, parent, module): """ :returns: An XML node with the details of an :obj:`euphorie.content.module`. """ node = etree.SubElement(parent, "module", optional="true" if module.optional else "false") if getattr(module, "external_id", None): node.attrib["external-id"] = module.external_id etree.SubElement(node, "title").text = module.title if HasText(module.description): etree.SubElement(node, "description").text = StripUnwanted( module.description) if module.optional: etree.SubElement(node, "question").text = module.question if StripMarkup(module.solution_direction): etree.SubElement(node, "solution-direction").text = StripUnwanted( module.solution_direction) if module.image is not None: self.exportImage(node, module.image, module.caption) for child in module.values(): if IModule.providedBy(child): self.exportModule(node, child) elif IRisk.providedBy(child): self.exportRisk(node, child) return node
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 exportProfileQuestion(self, parent, profile): node = etree.SubElement(parent, "profile-question") if getattr(profile, "external_id", None): node.attrib["external-id"] = profile.external_id etree.SubElement(node, "title").text = profile.title # Use title if question is not available (Euphorie < 2.0rc2 data) etree.SubElement(node, "question").text = \ profile.question or profile.title if HasText(profile.description): etree.SubElement(node, "description").text = profile.description for child in profile.values(): if IModule.providedBy(child): self.exportModule(node, child) elif IRisk.providedBy(child): self.exportRisk(node, child) return node
def copyTemplate(self, source, target): target = self.context[target.id] # Acquisition-wrap try: source._notifyOfCopyTo(target, op=0) except ConflictError: raise copy = source._getCopy(target) today = datetime.date.today() title = self.request.locale.dates.getFormatter("date", length="long").format( datetime.date.today() ) copy.id = today.isoformat() copy.title = title source_algorithm = aq_parent(source).evaluation_algorithm target_algorithm = self.request.form.get( "form.widgets.evaluation_algorithm", [source_algorithm] ).pop() target.evaluation_algorithm = target_algorithm target._setObject(copy.id, copy) if source_algorithm != target_algorithm: from euphorie.content.risk import EnsureInterface from euphorie.content.risk import IRisk risks = [ item for (id, item) in target.ZopeFind(target, search_sub=1) if IRisk.providedBy(item) ] for risk in risks: EnsureInterface(risk) if hasattr(copy, "published"): delattr(copy, "published") copy = target[copy.id] # Acquisition-wrap copy.wl_clearLocks() copy._postCopy(target, op=0) wt = api.portal.get_tool("portal_workflow") if wt.getInfoFor(copy, "review_state") == "published": wt.doActionFor(copy, "retract") notify(ObjectClonedEvent(target[copy.id])) return copy
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 migrate_actgion_plans(context): # Work in chunks of 25 max_tools = 25 site = api.portal.get() client = getattr(site, "client") today = date.today() request = context.REQUEST.clone() alsoProvides(request, IClientSkinLayer) # path = "eu/maritime-transport/maritime-transport-1" tool_paths = Session.query(model.SurveySession.zodb_path).distinct() # .filter(model.SurveySession.zodb_path==path).distinct() tool_count = 0 skip_count = 0 for result in tool_paths: tool_path = str(result[0]) try: tool = client.restrictedTraverse(tool_path) except KeyError: log.warning("No tool in client found for {}".format(tool_path)) continue country = tool_path.split("/")[0] sessions = ( Session.query(model.SurveySession).filter( and_( model.Account.id == model.SurveySession.account_id, model.Account.account_type != "guest", model.SurveySession.zodb_path == tool_path, model.SurveySession.migrated == None, # noqa: E711 )).order_by(model.SurveySession.zodb_path)) if not sessions.count(): skip_count += 1 if skip_count % 5 == 0: log.info("Skipped the first %d, already handled" % skip_count) continue log.info("\n\nHandle tool {}".format(tool_path)) risks_by_path = {} solutions_by_path = {} measures_by_path = {} for session in sessions: log.info("Session {}".format(session.id)) risks = (Session.query(model.Risk).filter( model.Risk.session_id == session.id).order_by(model.Risk.path)) for risk in risks: risk_path = str(risk.zodb_path) is_custom = "custom" in risk_path if is_custom: zodb_risk = None elif risk_path not in risks_by_path: try: zodb_risk = tool.restrictedTraverse(risk_path) except Exception: log.warning("Risk {} not found in tool {}".format( risk_path, tool_path)) continue else: if not IRisk.providedBy(zodb_risk): zodb_risk = None solutions_by_path[risk_path] = [] measures_by_path[risk_path] = [] else: solutions = zodb_risk._solutions solutions_by_path[risk_path] = solutions measures_by_path[ risk_path] = get_pre_defined_measures( solutions, country) risks_by_path[risk_path] = zodb_risk else: zodb_risk = risks_by_path[risk_path] # convert ActionPlan items that are clearly based on solutions # to "standard" type if not is_custom: for ap in risk.custom_measures: for solution in solutions_by_path[risk_path]: if solution.action_plan == (ap.action_plan or "").strip(): if (getattr(solution, "prevention_plan", "") or "").strip() == ( ap.prevention_plan or "") and (getattr( solution, "requirements", "") or "").strip() == ( ap.requirements or ""): ap.plan_type = "measure_standard" ap.solution_id = solution.id # Convert the measures-in-place to their respective ActionPlan items try: saved_existing_measures = (risk.existing_measures and loads(risk.existing_measures) or []) except ValueError: saved_existing_measures = [] # Backwards compat. We used to save dicts before we # switched to list of tuples. if isinstance(saved_existing_measures, dict): saved_existing_measures = [ (k, v) for (k, v) in saved_existing_measures.items() ] new_action_plans = [] already_converted_measure_ids = [ x.solution_id for x in risk.in_place_standard_measures ] already_converted_custom_texts = [ x.action for x in risk.in_place_custom_measures ] if saved_existing_measures: custom = [] while saved_existing_measures: text, active = saved_existing_measures.pop() if not active: continue if not is_custom and text in measures_by_path[ risk_path]: solution_id = measures_by_path[risk_path][text] if solution_id not in already_converted_measure_ids: new_action_plans.append( model.ActionPlan( action=text, plan_type="in_place_standard", solution_id=solution_id, )) else: if text not in already_converted_custom_texts: custom.append(text) for text in custom: new_action_plans.append( model.ActionPlan(action=text, plan_type="in_place_custom")) if new_action_plans: risk.action_plans.extend(new_action_plans) session.migrated = today tool_count += 1 if max_tools > 0 and tool_count >= max_tools: log.info("Broke off after %d tools" % tool_count) return