def _getIPloneFormGenFieldsPathTitlePair(self): formFolder = aq_parent(self) formFolderPath = formFolder.getPhysicalPath() formFieldTitles = [] for formField in formFolder.objectIds(): fieldObj = getattr(formFolder, formField) title = fieldObj.Title().strip() path = ",".join(fieldObj.getPhysicalPath()[len(formFolderPath):]) if IPloneFormGenField.providedBy(fieldObj): formFieldTitles.append((title, path)) # also allow mapping the filename and mimetype for file uploads if isinstance(fieldObj, FGFileField): formFieldTitles.append((title + ' Filename', path + ',filename')) formFieldTitles.append((title + ' Mimetype', path + ',mimetype')) # can we also inspect further down the chain if fieldObj.isPrincipiaFolderish: # since nested folders only go 1 level deep # a non-recursive approach approach will work here for subFormField in fieldObj.objectIds(): subFieldObj = getattr(fieldObj, subFormField) if IPloneFormGenField.providedBy(subFieldObj): # we append a list in this case formFieldTitles.append(("%s --> %s" % (fieldObj.Title().strip(), subFieldObj.Title().strip()), ",".join(subFieldObj.getPhysicalPath()[len(formFolderPath):]))) return formFieldTitles
def _getIPloneFormGenFieldsPathTitlePair(self): formFolder = aq_parent(self) formFolderPath = formFolder.getPhysicalPath() formFieldTitles = [] for formField in formFolder.objectIds(): fieldObj = getattr(formFolder, formField) title = fieldObj.Title().strip() path = ",".join(fieldObj.getPhysicalPath()[len(formFolderPath):]) if IPloneFormGenField.providedBy(fieldObj): formFieldTitles.append((title, path)) # also allow mapping the filename and mimetype for file uploads if isinstance(fieldObj, FGFileField): formFieldTitles.append( (title + ' Filename', path + ',filename')) formFieldTitles.append( (title + ' Mimetype', path + ',mimetype')) # can we also inspect further down the chain if fieldObj.isPrincipiaFolderish: # since nested folders only go 1 level deep # a non-recursive approach approach will work here for subFormField in fieldObj.objectIds(): subFieldObj = getattr(fieldObj, subFormField) if IPloneFormGenField.providedBy(subFieldObj): # we append a list in this case formFieldTitles.append( ("%s --> %s" % (fieldObj.Title().strip(), subFieldObj.Title().strip()), ",".join(subFieldObj.getPhysicalPath() [len(formFolderPath):]))) return formFieldTitles
def testDataGridFieldStaticFormFieldVocabsContainsAllPFGFormFields(self): """Our SalesforcePFGAdapter depends on the DataGridField which among other options allows for a Fixed Column that can be prepopulated using the fixed_rows attribute on the schema field. """ # create an adapter self.ff1.invokeFactory('SalesforcePFGAdapter', 'salesforce') for formField in self.ff1.objectIds(): fieldObj = getattr(self.ff1, formField) fixedRowFields = self.ff1.salesforce.generateFormFieldRows() static_titles_for_mapping = [mapping.initialData['form_field'] for mapping in fixedRowFields] if IPloneFormGenField.providedBy(fieldObj): self.failUnless(fieldObj.Title() in static_titles_for_mapping, "Field %s is not listed as a possible field in the computed widget expression \ method." % fieldObj.Title()) # let's add a new field to our form and immediately make sure it's # available as a row in our FixedRow form fields for the mapping self.ff1.invokeFactory('FormTextField', 'formtextfield') self.ff1.formtextfield.setTitle('My Form Text Field') fixedRowFields = self.ff1.salesforce.generateFormFieldRows() static_titles_for_mapping = [mapping.initialData['form_field'] for mapping in fixedRowFields] self.failUnless('My Form Text Field' in static_titles_for_mapping, "Field formtextfield is not listed as a possible field in the computed widget expression method.")
def testDataGridFieldStaticFormFieldVocabsContainsAllPFGFormFields(self): """Our SalesforcePFGAdapter depends on the DataGridField which among other options allows for a Fixed Column that can be prepopulated using the fixed_rows attribute on the schema field. """ # create an adapter self.ff1.invokeFactory('SalesforcePFGAdapter', 'salesforce') for formField in self.ff1.objectIds(): fieldObj = getattr(self.ff1, formField) fixedRowFields = self.ff1.salesforce.generateFormFieldRows() static_titles_for_mapping = [(mapping.initialData['form_field'], mapping.initialData['field_path']) \ for mapping in fixedRowFields] if IPloneFormGenField.providedBy(fieldObj): self.failUnless((fieldObj.Title(), fieldObj.getId()) in static_titles_for_mapping, "Field %s is not listed as a possible field in the computed widget expression \ method." % fieldObj.Title()) # let's add a new field to our form and immediately make sure it's # available as a row in our FixedRow form fields for the mapping self.ff1.invokeFactory('FormTextField', 'formtextfield') self.ff1.formtextfield.setTitle('My Form Text Field') fixedRowFields = self.ff1.salesforce.generateFormFieldRows() static_titles_for_mapping = [(mapping.initialData['form_field'], mapping.initialData['field_path']) \ for mapping in fixedRowFields] self.failUnless(('My Form Text Field', 'formtextfield') in static_titles_for_mapping, "Field formtextfield is not listed as a possible field in the computed widget expression method.")
def listFormFields(self): fields = [ (obj.getId(), obj.title_or_id()) for obj in self.aq_parent.objectValues() if IPloneFormGenField.providedBy(obj) ] return atapi.DisplayList(fields)
def listOptionalFormFields(self): fields = [ (obj.getId(), obj.title_or_id()) for obj in self.aq_parent.objectValues() if IPloneFormGenField.providedBy(obj) ] return atapi.DisplayList([(u"", _(u"Don't save"))] + fields)
def _getIPloneFormGenFieldProviderTitles(self): formFolder = aq_parent(self) formFieldTitles = [] for formField in formFolder.objectIds(): fieldObj = getattr(formFolder, formField) if IPloneFormGenField.providedBy(fieldObj): formFieldTitles.append(fieldObj.Title().strip()) return formFieldTitles
def getPFGFields(self): form = aq_parent(aq_inner(self)) if form.portal_type == 'TempFolder': form = aq_parent(form) values = [] for field in form.values(): if (IPloneFormGenField.providedBy(field) and not IStripeField.providedBy(field)): values.append((field.getId(), field.Title())) return DisplayList(values)
def getPFGFields(self): form = aq_parent(aq_inner(self)) if form.portal_type == 'TempFolder': form = aq_parent(form) values = [] for field in form.values(): if (IPloneFormGenField.providedBy(field) and not IStripeField.providedBy(field)): values.append(( field.getId(), field.Title())) return DisplayList(values)
def apply(self, pfg, initial_finish=True): """ Apply changes to the underlying PloneFormGen form based on the submitted values. """ data = self.getContent() existing_fields = [f.getId() for f in pfg.objectValues() if IPloneFormGenField.providedBy(f) and not f.getServerSide()] fields = data['fields'] for field_id, field_attrs in sorted(fields.items(), key=lambda x: x[1]['order']): if 'field_type' in field_attrs: field_type = field_attrs['field_type'] else: field_type = 'string' f_portal_type = field_type_to_portal_type_map.get(field_type, 'FormStringField') if field_id not in existing_fields: pfg.invokeFactory(id=field_id, type_name=f_portal_type) field = getattr(pfg, field_id) field.setTitle(field_attrs['title'].encode('utf8')) field.setDescription(field_attrs['description'].encode('utf8')) field.setRequired(field_attrs.get('required', False)) if 'default' in field_attrs: default = field_attrs['default'] if isinstance(default, unicode): default = default.encode('utf8') field.setFgDefault(default) if 'validator' in field_attrs: field.setFgStringValidator(field_attrs['validator']) if 'vocab' in field_attrs: field.setFgVocabulary(field_attrs['vocab']) if 'size' in field_attrs: field.setFgsize(field_attrs['size']) if field_type == 'text': field.setValidateNoLinkSpam(True) # sync removed fields to_delete = [] for f in existing_fields: if f not in fields: to_delete.append(f) pfg.manage_delObjects(to_delete) # adjust order if not initial_finish: sorted_field_ids = [k for k, v in sorted(fields.items(), key=lambda x: x[1]['order'])] pfg.moveObjectsByDelta(sorted_field_ids, -len(sorted_field_ids)) # reindex fields for f in pfg.objectValues(): f.reindexObject()
def _getIPloneFormGenFieldsPathTitlePair(self): formFolder = aq_parent(self) formFolderPath = formFolder.getPhysicalPath() formFieldTitles = [] for formField in formFolder.objectIds(): fieldObj = getattr(formFolder, formField) if IPloneFormGenField.providedBy(fieldObj): formFieldTitles.append((fieldObj.Title().strip(), ",".join(fieldObj.getPhysicalPath()[len(formFolderPath):]))) # can we also inspect further down the chain if fieldObj.isPrincipiaFolderish: # since nested folders only go 1 level deep # a non-recursive approach approach will work here for subFormField in fieldObj.objectIds(): subFieldObj = getattr(fieldObj, subFormField) if IPloneFormGenField.providedBy(subFieldObj): # we append a list in this case formFieldTitles.append(("%s --> %s" % (fieldObj.Title().strip(), subFieldObj.Title().strip()), ",".join(subFieldObj.getPhysicalPath()[len(formFolderPath):]))) return formFieldTitles
def load(self, pfg): data = self.getContent() if IAdding.providedBy(pfg): return data fields = data.setdefault('fields', {}) i = 0 for f in pfg.objectValues(): if IPloneFormGenField.providedBy(f): if f.getServerSide(): continue fieldinfo = { 'field_type': None, 'title': safe_unicode(f.Title()), 'description': safe_unicode(f.Description()), 'required': f.getRequired(), 'order': i, } if hasattr(f, 'getFgDefault'): fieldinfo['default'] = safe_unicode(f.getFgDefault()) if f.portal_type == 'FormStringField': fieldinfo['field_type'] = 'string' fieldinfo['validator'] = f.getFgStringValidator() if not fieldinfo['validator']: fieldinfo['validator'] = 'vocabulary_none_text' try: fieldinfo['size'] = int(f.getFgsize()) except TypeError: fieldinfo['size'] = 30 if f.portal_type == 'FormTextField': fieldinfo['field_type'] = 'text' if f.portal_type == 'FormBooleanField': fieldinfo['field_type'] = 'boolean' # make sure we match one of the vocab terms if fieldinfo['default'] is not True: fieldinfo['default'] = False if f.portal_type == 'FormSelectionField': fieldinfo['field_type'] = 'selection' fieldinfo['vocab'] = safe_unicode("\n".join(f.getFgVocabulary())) if f.portal_type == 'FormMultiSelectionField': fieldinfo['field_type'] = 'multiselection' fieldinfo['vocab'] = safe_unicode("\n".join(f.getFgVocabulary())) if f.portal_type == 'FormCaptchaField': fieldinfo['field_type'] = 'captcha' fields[f.getId()] = fieldinfo i += 1
def getLogEntry(self): ''' Get's a log entry for your action ''' event = self.event obj = event.object data = {'info': ''} # order of those checks is important since some interfaces # base off the others if IPloneFormGenField.providedBy(obj): # if ploneformgen field, use parent object for modified data data['field'] = obj.getId() obj = aq_parent(obj) # the order of those interface checks matters since some interfaces # inherit from others if IObjectRemovedEvent.providedBy(event): # need to keep track of removed events so it doesn't get called # more than once for each object action = 'removed' elif ( IObjectInitializedEvent.providedBy(event) or IObjectCreatedEvent.providedBy(event) or IObjectAddedEvent.providedBy(event) ): action = 'added' elif IObjectMovedEvent.providedBy(event): # moves can also be renames. Check the parent object if event.oldParent == event.newParent: if 'Rename' not in self.rule.rule.title: # cut out here, double action for this event return {} data['info'] = 'previous id: %s' % event.oldName action = 'rename' else: if 'Moved' not in self.rule.rule.title: # step out immediately since this could be a double action return {} data['info'] = 'previous location: %s/%s' % ( '/'.join(event.oldParent.getPhysicalPath()), event.oldName, ) action = 'moved' elif IObjectModifiedEvent.providedBy(event): action = 'modified' elif IActionSucceededEvent.providedBy(event): data['info'] = 'workflow transition: %s; comments: %s' % ( event.action, self.get_history_comment(), ) action = 'workflow' elif IObjectClonedEvent.providedBy(event): action = 'copied' elif ICheckinEvent.providedBy(event): data['info'] = event.message action = 'checked in' self.request.environ['disable.auditlog'] = True data['working_copy'] = '/'.join(obj.getPhysicalPath()) obj = event.baseline elif IBeforeCheckoutEvent.providedBy(event): action = 'checked out' self.request.environ['disable.auditlog'] = True elif ICancelCheckoutEvent.providedBy(event): action = 'cancel check out' self.request.environ['disable.auditlog'] = True data['working_copy'] = '/'.join(obj.getPhysicalPath()) obj = event.baseline else: logger.warn('no action matched') return {} if IWorkingCopy.providedBy(obj): # if working copy, iterate, check if Track Working Copies is # enabled if not self.trackWorkingCopies: # if not enabled, we only care about checked messages if 'check' not in action: return {} # if enabled in control panel, use original object and move # working copy path to working_copy data['working_copy'] = '/'.join(obj.getPhysicalPath()) relationships = obj.getReferences( WorkingCopyRelation.relationship) # check relationships, if none, something is wrong, not logging # action if len(relationships) <= 0: return {} obj = relationships[0] data.update(self._getObjectInfo(obj)) data['action'] = action return data
def listOptionalFormFields(self): fields = [(obj.getId(), obj.title_or_id()) for obj in self.aq_parent.objectValues() if IPloneFormGenField.providedBy(obj)] return atapi.DisplayList([(u'', _(u"Don't save"))] + fields)
def getLogEntry(self): ''' Get's a log entry for your action ''' event = self.event obj = event.object data = {'info': ''} # order of those checks is important since some interfaces # base off the others if IPloneFormGenField.providedBy(obj): # if ploneformgen field, use parent object for modified data data['field'] = obj.getId() obj = aq_parent(obj) # the order of those interface checks matters since some interfaces # inherit from others if IObjectRemovedEvent.providedBy(event): # need to keep track of removed events so it doesn't get called # more than once for each object action = 'removed' elif (IObjectInitializedEvent.providedBy(event) or IObjectCreatedEvent.providedBy(event) or IObjectAddedEvent.providedBy(event)): action = 'added' elif IObjectMovedEvent.providedBy(event): # moves can also be renames. Check the parent object if event.oldParent == event.newParent: if 'Rename' not in self.rule.rule.title: # cut out here, double action for this event return {} data['info'] = 'previous id: %s' % event.oldName action = 'rename' else: if 'Moved' not in self.rule.rule.title: # step out immediately since this could be a double action return {} data['info'] = 'previous location: %s/%s' % ( '/'.join(event.oldParent.getPhysicalPath()), event.oldName, ) action = 'moved' elif IObjectModifiedEvent.providedBy(event): action = 'modified' elif IActionSucceededEvent.providedBy(event): data['info'] = 'workflow transition: %s; comments: %s' % ( event.action, self.get_history_comment(), ) action = 'workflow' elif IObjectClonedEvent.providedBy(event): action = 'copied' elif ICheckinEvent.providedBy(event): data['info'] = event.message action = 'checked in' self.request.environ['disable.auditlog'] = True data['working_copy'] = '/'.join(obj.getPhysicalPath()) obj = event.baseline elif IBeforeCheckoutEvent.providedBy(event): action = 'checked out' self.request.environ['disable.auditlog'] = True elif ICancelCheckoutEvent.providedBy(event): action = 'cancel check out' self.request.environ['disable.auditlog'] = True data['working_copy'] = '/'.join(obj.getPhysicalPath()) obj = event.baseline else: logger.warn('no action matched') return {} if IWorkingCopy.providedBy(obj): # if working copy, iterate, check if Track Working Copies is # enabled if not self.trackWorkingCopies: # if not enabled, we only care about checked messages if 'check' not in action: return {} # if enabled in control panel, use original object and move # working copy path to working_copy data['working_copy'] = '/'.join(obj.getPhysicalPath()) relationships = obj.getReferences(WorkingCopyRelation.relationship) # check relationships, if none, something is wrong, not logging # action if len(relationships) <= 0: return {} obj = relationships[0] data.update(self._getObjectInfo(obj)) data['action'] = action return data
def listFormFields(self): fields = [(obj.getId(), obj.title_or_id()) for obj in self.aq_parent.objectValues() if IPloneFormGenField.providedBy(obj)] return atapi.DisplayList(fields)
def __call__(self): req = getRequest() if req.environ.get('disable.auditlog', False): return True event = self.event obj = event.object # order of those checks is important since some interfaces # base off the others rule = inspect.stack()[1][0].f_locals.get('self', None) registry = getUtility(IRegistry) trackWorkingCopies = registry['collective.auditlog.interfaces.IAuditLogSettings.trackworkingcopies'] # noqa if not self.canExecute(rule, req): return True # cut out early, we can't do this event data = { 'info': '' } if IPloneFormGenField.providedBy(obj): # if ploneformgen field, use parent object for modified data data['field'] = obj.getId() obj = aq_parent(obj) # the order of those interface checks matters since some interfaces # inherit from others if IObjectRemovedEvent.providedBy(event): # need to keep track of removed events so it doesn't get called # more than once for each object action = 'removed' elif (IObjectInitializedEvent.providedBy(event) or IObjectCreatedEvent.providedBy(event) or IObjectAddedEvent.providedBy(event)): action = 'added' elif IObjectMovedEvent.providedBy(event): # moves can also be renames. Check the parent object if event.oldParent == event.newParent: if rule is None or 'Rename' in rule.rule.title: info = {'previous_id': event.oldName} data['info'] = json.dumps(info) action = 'rename' else: # cut out here, double action for this event return True else: if rule is None or 'Moved' in rule.rule.title: parent_path = '/'.join(event.oldParent.getPhysicalPath()) previous_location = parent_path + '/' + event.oldName info = {'previous_location': previous_location} data['info'] = json.dumps(info) action = 'moved' else: # step out immediately since this could be a double action return True elif IObjectModifiedEvent.providedBy(event): action = 'modified' elif IActionSucceededEvent.providedBy(event): info = {'transition': event.action, 'comments': self.get_history_comment()} data['info'] = json.dumps(info) action = 'workflow' elif IObjectClonedEvent.providedBy(event): action = 'copied' elif ICheckinEvent.providedBy(event): info = {'message': event.message} data['info'] = json.dumps(info) action = 'checked in' req.environ['disable.auditlog'] = True data['working_copy'] = '/'.join(obj.getPhysicalPath()) obj = event.baseline elif IBeforeCheckoutEvent.providedBy(event): action = 'checked out' req.environ['disable.auditlog'] = True elif ICancelCheckoutEvent.providedBy(event): action = 'cancel check out' req.environ['disable.auditlog'] = True data['working_copy'] = '/'.join(obj.getPhysicalPath()) obj = event.baseline elif IUserLoggedInEvent.providedBy(event): action = 'logged in' info = {'user': event.object.getUserName()} data['info'] = json.dumps(info) elif IUserLoggedOutEvent.providedBy(event): action = 'logged out' else: logger.warn('no action matched') return True if IWorkingCopy.providedBy(obj): # if working copy, iterate, check if Track Working Copies is # enabled if trackWorkingCopies: # if enabled in control panel, use original object and move # working copy path to working_copy data['working_copy'] = '/'.join(obj.getPhysicalPath()) relationships = obj.getReferences( WorkingCopyRelation.relationship) # check relationships, if none, something is wrong, not logging # action if len(relationships) > 0: obj = relationships[0] else: return True else: # if not enabled, we only care about checked messages if 'check' not in action: return True data.update(getObjectInfo(obj)) data['action'] = action addLogEntry(obj, data) return True