def _add_single_record_type_entries( self, rt_element: MetadataElement, api_name: str, picklist: str, entry: Dict ): # Locate, or add, the root picklistValues element for this picklist. picklist_element = rt_element.find( "picklistValues", picklist=picklist ) or rt_element.append("picklistValues") if not picklist_element.find("picklist", text=picklist): picklist_element.append("picklist", text=picklist) # If this picklist value entry is not already present, add it. default = str(process_bool_arg(entry.get("default", False))).lower fullName = entry["fullName"] # The Metadata API's behavior with picklist values in record types # is to return partially URL-encoded values. Most punctuation appears # to be escaped, but spaces and high-bit characters are not. # To route around this, we compare the `unquote()`-ed # value of each element, since we don't know in 100% of cases # how to make our input look like what MDAPI returns. # Note that this behavior is different from picklist values in value sets. def find_matching_value(picklist, target): return next( filter( lambda x: unquote(x.fullName.text) == target, picklist.findall("values"), ), None, ) values = find_matching_value(picklist_element, fullName) if not values: add_before = entry.get("add_before") if add_before: before_elem = find_matching_value(picklist_element, add_before) if before_elem: values = picklist_element.insert_before(before_elem, "values") else: values = picklist_element.append("values") else: values = picklist_element.append("values") # The Metadata API does _not_ require us to perform its partial URL-encoding to deploy. values.append("fullName", text=fullName) values.append("default", text=str(default).lower()) # If this picklist value needs to be made default, remove any existing default. if default: # Find existing default and remove it, while setting our value as default for value in picklist_element.values: default = value.find("default") if default: default.text = ( "false" if value.fullName.text != fullName else "true" )
def _add_record_type_entries(self, metadata: MetadataElement, api_name: str, picklist: str, entry: Dict): if "*" in self.options["record_types"]: rt_list = metadata.findall("recordTypes") else: rt_list = [ metadata.find("recordTypes", fullName=record_type) for record_type in self.options["record_types"] ] for rt_element in rt_list: # Silently ignore record types that don't exist in the target org. if rt_element: self._add_single_record_type_entries(rt_element, api_name, picklist, entry)
def _transform_entity(self, metadata: MetadataElement, api_name: str) -> MetadataElement: """Finds metadata's first child with tag. If no child is found, appends a new child with tag. Then updates child's text as the value option.""" tag = self.options["tag"] child = metadata.find(tag) if child is None: child = metadata.append(tag) child.text = self.options["value"] self.logger.info(f'Updating {self.entity} "{api_name}":') self.logger.info(f' {tag} as "{child.text}"') return metadata
def _transform_entity(self, metadata: MetadataElement, api_name: str) -> Optional[MetadataElement]: status = "true" if process_bool_arg( self.options["active"]) else "false" metadata.find("isActive").text = status return metadata
def _transform_entity(self, metadata: MetadataElement, api_name: str): for entry in self.options.get("entries", []): if "fullName" not in entry or "label" not in entry: raise TaskOptionsError( "Standard value set entries must contain the 'fullName' and 'label' keys." ) # Check for extra metadata on CaseStatus and OpportunityStage if api_name == "OpportunityStage": if not all([ "closed" in entry, "forecastCategory" in entry, "probability" in entry, "won" in entry, ]): raise TaskOptionsError( "OpportunityStage standard value set entries require the keys " "'closed', 'forecastCategory', 'probability', and 'won'" ) if api_name == "CaseStatus": if "closed" not in entry: raise TaskOptionsError( "CaseStatus standard value set entries require the key 'closed'" ) existing_entry = metadata.findall("standardValue", fullName=entry["fullName"]) if not existing_entry: # Entry doesn't exist. Insert it. elem = metadata.append(tag="standardValue") elem.append("fullName", text=entry["fullName"]) elem.append("label", text=entry["label"]) elem.append("default", text="false") if api_name in ["OpportunityStage", "CaseStatus"]: elem.append("closed", str(entry["closed"]).lower()) if api_name == "OpportunityStage": elem.append("won", str(entry["won"]).lower()) elem.append("probability", str(entry["probability"])) elem.append("forecastCategory", entry["forecastCategory"]) return metadata
def _transform_entity( self, metadata: MetadataElement, api_name: str ) -> MetadataElement: desired_internal_model = self.owds[api_name].get("internal_sharing_model") desired_external_model = self.owds[api_name].get("external_sharing_model") if desired_external_model: external_model = metadata.find("externalSharingModel") if not external_model: external_model = metadata.append("externalSharingModel") external_model.text = desired_external_model if desired_internal_model: internal_model = metadata.find("sharingModel") if not internal_model: internal_model = metadata.append("sharingModel") internal_model.text = desired_internal_model return metadata
def _transform_entity(self, metadata: MetadataElement, api_name: str) -> Optional[MetadataElement]: related_list = self._inject_namespace(self.options["related_list"]) existing_related_lists = metadata.findall("relatedLists", relatedList=related_list) if existing_related_lists: return None self._create_new_related_list(metadata, api_name, related_list) return metadata
def _add_picklist_field_entry(self, vsd: MetadataElement, api_name: str, picklist: str, entry: Dict): fullName = entry["fullName"] label = entry.get("label") or fullName default = entry.get("default", False) add_before = entry.get("add_before") if vsd.find("value", fullName=fullName): self.logger.warning( f"Picklist entry with fullName {fullName} already exists on picklist {picklist}." ) else: if add_before and vsd.find("value", fullName=add_before): entry_element = vsd.insert_before( vsd.find("value", fullName=add_before), "value") else: entry_element = vsd.append("value") entry_element.append("fullName", text=fullName) entry_element.append("label", text=label) entry_element.append("default", text=str(default).lower()) # If we're setting this as the default, unset all of the other entries. if default: for value in vsd.findall("value"): default = value.find("default") if default: default.text = ("false" if value.fullName.text != fullName else "true")
def _modify_picklist(self, metadata: MetadataElement, api_name: str, picklist: str): # Locate the <fields> entry for this picklist. field = metadata.find("fields", fullName=picklist) if not field: raise TaskOptionsError(f"The field {api_name}.{picklist} was not found.") vsd = field.valueSet.find("valueSetDefinition") if not vsd: raise TaskOptionsError( f"The picklist {api_name}.{picklist} uses a Global Value Set, which is not supported." ) # Update each entry in this picklist, and also add to all record types. for entry in self.options["entries"]: self._add_picklist_field_entry(vsd, api_name, picklist, entry) if self.options["record_types"]: self._add_record_type_entries(metadata, api_name, picklist, entry)
def _modify_help_text( self, metadata: MetadataElement, api_name: str, custom_field: str, help_text: str, ): # Locate the <fields> entry for this field entry. field = metadata.find("fields", fullName=custom_field) if not field: raise TaskOptionsError( f"The field {api_name}.{custom_field} was not found.") try: if (field.inlineHelpText.text == "" or field.inlineHelpText.text == help_text or self.options["overwrite"]): field.inlineHelpText.text = help_text else: self.logger.warning( f"Help text for field {api_name} has a different value. " "Set the overwrite option to True to overwrite this field help text." ) except AttributeError: field.append("inlineHelpText", text=help_text)