def setUp(self): super(NyAccess2LevelTestCase, self).setUp() self.perm1, self.perm2 = 'View', 'View History' self.role1, self.role2 = 'Contributor', 'Reviewer' addNyFolder(self.portal.info, 'testfolderparent', contributor='admin', submission=1) self.testfolderparent = self.portal.info.testfolderparent addNyFolder(self.testfolderparent, 'testfolder', contributor='admin', submission=1) self.testfolder = self.testfolderparent.testfolder # NOTE: this is *not* the way to use NyAccess. It should never # be stored in the database. It should be set as an attribute # to a *class*, like NyForum. self.testfolderparent._setOb( 'ny_access', NyAccess('ny_access', { self.perm1: self.perm1, self.perm2: self.perm2 })) self.testfolder._setOb( 'ny_access', NyAccess('ny_access', { self.perm1: self.perm1, self.perm2: self.perm2 })) # default permission map # parent folder does not inherit permissions permission = Permission(self.perm1, (), self.testfolderparent) permission.setRoles((self.role1, 'Manager')) permission = Permission(self.perm2, (), self.testfolderparent) permission.setRoles((self.role2, 'Manager')) # child folder permissions permission = Permission(self.perm1, (), self.testfolder) permission.setRoles([self.role2]) permission = Permission(self.perm2, (), self.testfolder) permission.setRoles((self.role1, 'Manager')) transaction.commit()
def setUp(self): super(NyAccessTestCase, self).setUp() addNyFolder(self.portal.info, 'testfolder', contributor='admin', submission=1) self.testfolder = self.portal.info.testfolder # NOTE: this is *not* the way to use NyAccess. It should never # be stored in the database. It should be set as an attribute # to a *class*, like NyForum. self.testfolder._setOb( 'ny_access', NyAccess('ny_access', { 'View': 'View', 'View History': 'View History' })) transaction.commit()
class MegaSurvey(SurveyQuestionnaire, BaseSurveyTemplate): """ """ meta_type = 'Naaya Mega Survey' meta_label = 'Survey' _constructors = (manage_addMegaSurvey, ) security = ClassSecurityInfo() edit_access = NyAccess( 'edit_access', { PERMISSION_ADD_ANSWER: "Submit answer", PERMISSION_ADD_REPORT: "Create report", PERMISSION_ADD_ATTACHMENT: "Attach file", PERMISSION_VIEW_ANSWERS: "View answers", PERMISSION_EDIT_ANSWERS: "Edit answers", PERMISSION_VIEW_REPORTS: "View reports", }) def __init__(self, id, **kwargs): """ """ # BaseSurveyTemplate.__init__(self, id, **kwargs) SurveyQuestionnaire.__init__(self, id, None, **kwargs) self.contributor = kwargs.get('contributor') self.approved = 1 def can_be_seen(self): """ Indicates if the current user has access to the current folder. """ return self.checkPermission(view) def all_meta_types(self, interfaces=None): """What can you put inside me?""" return BaseSurveyTemplate.all_meta_types(self, interfaces) def getSurveyTemplate(self): """ """ return self security.declareProtected(view, 'download') def download(self, REQUEST=None, RESPONSE=None): """returns all the answers in a csv file""" def stringify(value): if not isinstance(value, basestring): value = unicode(value) if isinstance(value, str): return unicode(value, 'utf-8') return value def all_stringify(row): return [stringify(value) for value in row] answers = self.getAnswers() widgets = self.getSortedWidgets() header = ['Respondent'] for widget in widgets: header += [widget.title_or_id()] if widget.meta_type == 'Naaya Radio Matrix Widget': header += widget.rows rows = [answer.answer_values() for answer in answers] rows = [all_stringify(item) for item in rows] file_type = REQUEST.get('file_type', 'CSV') if file_type == 'CSV': RESPONSE.setHeader('Content-Type', 'text/csv') RESPONSE.setHeader('Content-Disposition', 'attachment; filename=%s.csv' % self.id) return generate_csv(header, rows) if file_type == 'Excel' and self.rstk.we_provide('Excel export'): RESPONSE.setHeader('Content-Type', 'application/vnd.ms-excel') RESPONSE.setHeader('Content-Disposition', 'attachment; filename=%s.xls' % self.id) return generate_excel(header, rows) else: raise ValueError('unknown file format %r' % file_type) # # Site pages # security.declareProtected(view, 'index_html') def index_html(self): """ """ if (not self.checkPermissionSkipCaptcha() and not self.recaptcha_is_present()): raise ValueError("Invalid recaptcha keys") return self._index_html() _index_html = NaayaPageTemplateFile('zpt/megasurvey_index', globals(), 'NaayaSurvey.megasurvey_index') security.declareProtected(PERMISSION_EDIT_OBJECTS, 'edit_html') edit_html = NaayaPageTemplateFile('zpt/megasurvey_edit', globals(), 'NaayaSurvey.megasurvey_edit') security.declareProtected(PERMISSION_EDIT_OBJECTS, 'edit_attachments_html') edit_attachments_html = NaayaPageTemplateFile( 'zpt/megasurvey_edit_attachments', globals(), 'NaayaSurvey.megasurvey_edit_attachments') security.declareProtected(PERMISSION_EDIT_OBJECTS, 'edit_questions_html') edit_questions_html = NaayaPageTemplateFile( 'zpt/megasurvey_edit_questions', globals(), 'NaayaSurvey.megasurvey_edit_questions') security.declareProtected(PERMISSION_EDIT_OBJECTS, 'edit_reports_html') edit_reports_html = NaayaPageTemplateFile( 'zpt/megasurvey_edit_reports', globals(), 'NaayaSurvey.megasurvey_edit_reports') # # change the security of the inherited methods # security.declareProtected(PERMISSION_EDIT_OBJECTS, 'saveProperties') security.declareProtected(PERMISSION_EDIT_OBJECTS, 'addWidget') security.declareProtected(PERMISSION_EDIT_OBJECTS, 'deleteItems') security.declareProtected(PERMISSION_EDIT_OBJECTS, 'setSortOrder') security.declareProtected(PERMISSION_EDIT_OBJECTS, 'addReport') security.declareProtected(PERMISSION_EDIT_OBJECTS, 'generateFullReport') security.declareProtected(PERMISSION_EDIT_OBJECTS, 'addAttachment') # static files css_survey_common = DTMLFile('www/survey_common.css', globals()) css_survey_print = DTMLFile('www/survey_print.css', globals()) fancy_checkmark = ImageFile('www/fancy_checkmark.gif', globals()) survey_js = ImageFile('www/survey.js', globals()) security.declareProtected(PERMISSION_EDIT_ANSWERS, 'bogus') def bogus(self): """ Needed in Naaya Access. It is mandatory that a permission must be declared so it can be used in Naaya Access. This should be removed once this issue is solved """ pass security.declarePublic('display_admin_warning') def display_admin_warning(self): return self.checkPermissionPublishObjects()\ and self.anonymous_has_access()\ and not self.recaptcha_is_present()\ and not self.anonymous_skips_captcha() security.declarePublic('anonymous_has_access') def anonymous_has_access(self): return 'Anonymous' in self.edit_access.getPermissionMapping( )['Naaya - Add Naaya Survey Answer'] security.declarePublic('anonymous_skips_captcha') def anonymous_skips_captcha(self): permission = 'Naaya - Skip Captcha' permission_object = Permission(permission, (), self) return 'Anonymous' in permission_object.getRoles() security.declarePrivate('dont_inherit_view_permission') def dont_inherit_view_permission(self): permission = Permission(view, (), self) roles = permission.getRoles() roles = tuple(set(roles) | set(['Manager', 'Administrator', 'Owner'])) permission.setRoles(roles) security.declarePrivate('inherit_view_permission') def inherit_view_permission(self): permission = Permission(view, (), self) roles = permission.getRoles() roles = list(roles) permission.setRoles(roles)
class NyConsultation(NyAttributes, Implicit, NyProperties, BTreeFolder2, NyContainer, NyCheckControl, NyValidation, utils): """ """ meta_type = METATYPE_OBJECT meta_label = LABEL_OBJECT all_meta_types = () icon = 'misc_/NaayaContent/NyConsultation.gif' icon_marked = 'misc_/NaayaContent/NyConsultation_marked.gif' title = LocalProperty('title') description = LocalProperty('description') security = ClassSecurityInfo() edit_access = NyAccess( 'edit_access', { PERMISSION_REVIEW_CONSULTATION: "Submit comments", PERMISSION_VIEW_CONSULTATION: "View consultation", PERMISSION_MANAGE_CONSULTATION: "Administer consultation", }) def __init__(self, id, title, description, sortorder, start_date, end_date, public_registration, allow_file, line_comments, contributor, releasedate, lang): """ """ self.id = id NyValidation.__dict__['__init__'](self) NyCheckControl.__dict__['__init__'](self) NyContainer.__dict__['__init__'](self) BTreeFolder2.__init__(self) self.contributor = contributor self.questions = {} try: del self.title except: pass self.save_properties(title, description, sortorder, start_date, end_date, public_registration, allow_file, line_comments, releasedate, lang) NyProperties.__dict__['__init__'](self) self.submitted = 1 security.declarePrivate('save_properties') def save_properties(self, title, description, sortorder, start_date, end_date, public_registration, allow_file, line_comments, releasedate, lang): self._setLocalPropValue('title', lang, title) self._setLocalPropValue('description', lang, description) if not hasattr(self, 'imageContainer'): self.imageContainer = NyImageContainer(self, True) if start_date: self.start_date = self.utConvertStringToDateTimeObj(start_date) else: self.start_date = self.utGetTodayDate() if end_date: self.end_date = self.utConvertStringToDateTimeObj(end_date) else: self.end_date = self.utGetTodayDate() self.sortorder = sortorder self.releasedate = releasedate self.public_registration = public_registration self.allow_file = allow_file self.line_comments = line_comments security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'saveProperties') def saveProperties(self, title='', description='', sortorder='', start_date='', end_date='', public_registration='', allow_file='', line_comments='', file='', lang='', REQUEST=None): """ """ if not title: self.setSession('title', title) self.setSession('description', description) self.setSessionErrors(['The Title field must have a value.']) return REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' % (self.absolute_url(), lang)) if file and not file.read(): self.setSession('title', title) self.setSession('description', description) self.setSessionErrors(['File must not be empty']) return REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' % (self.absolute_url(), lang)) exfile = self.get_exfile() if file and exfile: exfile.saveUpload(file=file, lang=lang) downloadfilename = file.filename exfile._setLocalPropValue('downloadfilename', lang, downloadfilename) elif file and not exfile: addNyExFile(self, title=title, file=file, lang=lang, source='file') releasedate = self.releasedate self.updateRequestRoleStatus(public_registration, lang) self.save_properties(title, description, sortorder, start_date, end_date, public_registration, allow_file, line_comments, releasedate, lang) if REQUEST: self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES, date=self.utGetTodayDate()) REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' % (self.absolute_url(), lang)) security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'updateRequestRoleStatus') def updateRequestRoleStatus(self, public_registration, lang): if public_registration: self.updateDynamicProperties( self.processDynamicProperties( METATYPE_OBJECT, {'show_contributor_request_role': 'on'}), lang) if not public_registration: self.updateDynamicProperties( self.processDynamicProperties( METATYPE_OBJECT, {'show_contributor_request_role': ''}), lang) security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'checkReviewerRole') def checkReviewerRole(self): """ Checks if the 'Reviewer' role exists, creates and adds review permissions if it doesn't exist """ auth_tool = self.getAuthenticationTool() roles = auth_tool.list_all_roles() PERMISSION_GROUP = 'Review content' if 'Reviewer' not in roles: auth_tool.addRole('Reviewer', [PERMISSION_REVIEW_CONSULTATION]) else: permission_add_role(self, PERMISSION_REVIEW_CONSULTATION, 'Reviewer') #give permissions to administrators admin_permissions = self.permissionsOfRole('Administrator') site = self.getSite() if PERMISSION_MANAGE_CONSULTATION not in admin_permissions: site.manage_permission(PERMISSION_MANAGE_CONSULTATION, ('Administrator', ), acquire=1) site.manage_permission(PERMISSION_VIEW_CONSULTATION, ('Administrator', ), acquire=1) site.manage_permission(PERMISSION_REVIEW_CONSULTATION, ('Administrator', ), acquire=1) ######################## # Rate lists ######################## manage_addRateList = manage_addRateList security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'default_rating') def default_rating(self): self.admin_addratelist('Relevancy', 'Relevancy', 'Relevancy') self.admin_additem('Relevancy', '1', 'Less relevant') self.admin_additem('Relevancy', '2', 'Average relevant') self.admin_additem('Relevancy', '3', 'Very relevant') security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'getRateValue') def getRateValue(self, review, rate): """ """ try: return review.ratings[rate.title] except: return None security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'getRateLists') def getRateLists(self): return self.objectValues('Rate Item') security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'getRateListById') def getRateListById(self, p_id): #return the selection list with the given id try: ob = self._getOb(p_id) except: ob = None if ob is not None: if ob.meta_type != 'Rate Item': ob = None return ob security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'admin_deleteratelist') def admin_deleteratelist(self, ids=[], REQUEST=None): """ """ self.manage_delObjects(self.utConvertToList(ids)) if REQUEST: self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES, date=self.utGetTodayDate()) REQUEST.RESPONSE.redirect('%s/admin_ratelists_html' % self.absolute_url()) security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'admin_addratelist') def admin_addratelist(self, id='', title='', description='', REQUEST=None): """ """ self.manage_addRateList(id, title, description) if REQUEST: self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES, date=self.utGetTodayDate()) REQUEST.RESPONSE.redirect('%s/admin_ratelists_html' % self.absolute_url()) security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'admin_editratelist') def admin_editratelist(self, id='', title='', description='', REQUEST=None): """ """ ob = self.getRateListById(id) if ob is not None: ob.manageProperties(title, description) if REQUEST: self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES, date=self.utGetTodayDate()) REQUEST.RESPONSE.redirect('%s/admin_ratelist_html?id=%s' % (self.absolute_url(), id)) security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'admin_deleteitems') def admin_deleteitems(self, id='', ids=[], REQUEST=None): """ """ ob = self.getRateListById(id) if ob is not None: ob.manage_delete_items(self.utConvertToList(ids)) if REQUEST: self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES, date=self.utGetTodayDate()) REQUEST.RESPONSE.redirect('%s/admin_ratelist_html?id=%s' % (self.absolute_url(), id)) security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'admin_additem') def admin_additem(self, id='', item='', title='', REQUEST=None): """ """ ob = self.getRateListById(id) if ob is not None: ob.manage_add_item(item, title) if REQUEST: self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES, date=self.utGetTodayDate()) REQUEST.RESPONSE.redirect('%s/admin_ratelist_html?id=%s' % (self.absolute_url(), id)) security.declareProtected(view, 'get_consultation') def get_consultation(self): """ Returns this object""" return self security.declareProtected(view, 'get_consultation_url') def get_consultation_url(self): """ Returns this object's url""" return self.absolute_url() security.declareProtected(view, 'get_exfile') def get_exfile(self): """ Returns the first ExFile in the Consultation, there should be only one. """ try: exfile = self.objectValues(['Naaya Extended File'])[0] except IndexError: exfile = None return exfile security.declareProtected(view, 'get_exfile_url') def get_exfile_url(self, lang): """ Returns the exfile download url for the given language """ try: return self.get_exfile().getEditDownloadUrl(lang) except: return '[no_file]' security.declareProtected(view, 'check_exfile_for_lang') def check_exfile_for_lang(self, lang): """ Checks if there is a file uploaded for the given language. """ return self.get_exfile().getFileItem(lang).size > 0 security.declareProtected(view, 'get_exfile_langs') def get_exfile_langs(self): """ Returns the languages for witch NyExFile contains files. """ return [ language for language in self.getSite().gl_get_languages_map() if self.check_exfile_for_lang(language['id']) ] security.declareProtected(view, 'get_start_date') def get_start_date(self): """ Returns the start date in dd/mm/yyyy string format. """ return self.utConvertDateTimeObjToString(self.start_date) security.declareProtected(view, 'get_end_date') def get_end_date(self): """ Returns the end date in dd/mm/yyyy string format. """ return self.utConvertDateTimeObjToString(self.end_date) security.declareProtected(view, 'get_days_left') def get_days_left(self): """ Returns the remaining days for the consultation or the number of days before it starts """ today = self.utGetTodayDate().earliestTime() if self.start_date.lessThanEqualTo(today): return (1, int(str((self.end_date + 1) - today).split('.')[0])) else: return (0, int(str(self.start_date - today).split('.')[0])) security.declareProtected(view_management_screens, 'manage_options') def manage_options(self): """ """ l_options = (NyContainer.manage_options[0], ) l_options += ({ 'label': 'View', 'action': 'index_html' }, ) + NyContainer.manage_options[3:8] return l_options security.declareProtected(view, 'check_contributor_review') def check_contributor_review(self, contributor='', REQUEST=None): """ Returns True if user already posted a comment """ if not contributor and REQUEST: contributor = REQUEST.AUTHENTICATED_USER.getUserName() return contributor in [ review.contributor for review in self.objectValues(['Consultation Review']) ] security.declareProtected(PERMISSION_REVIEW_CONSULTATION, 'addConsultationReview') def addConsultationReview(self, contributor_name='', file='', REQUEST=None, **kwargs): """ """ contributor = REQUEST.AUTHENTICATED_USER.getUserName() if not contributor_name: self.setSession('contributor_name', contributor_name) self.setSessionErrors(['Fill in the name field.']) return REQUEST.RESPONSE.redirect(self.absolute_url() + '/review_add_html') if REQUEST: kwargs.update(REQUEST.form) if self.allow_file != '1': file = '' if self.line_comments != '1': kwargs['adt_comment'] = {} days = self.get_days_left() if days[0] == 1 and days[1] > 0 and self.get_exfile(): if not self.check_contributor_review(contributor): addConsultationReviewItem(self, contributor, contributor_name, file, kwargs) return REQUEST.RESPONSE.redirect(self.absolute_url() + '/review_add_html?status=ok') else: return REQUEST.RESPONSE.redirect( self.absolute_url() + '/review_add_html?status=failed') elif days[0] == 1 and days[1] <= 0: return REQUEST.RESPONSE.redirect(self.absolute_url() + '/review_add_html?status=late') elif days[0] <= 0: return REQUEST.RESPONSE.redirect(self.absolute_url() + '/review_add_html?status=soon') else: return REQUEST.RESPONSE.redirect(self.absolute_url()) def checkConsultationUser(self): """ Checks if the user is logged in and has reviewer rights: 0 if user is anonymous, 1 if user has reviewer role 2 if user doesn't have reviewer role """ review_check = self.checkPermissionReviewConsultation() if self.isAnonymousUser(): return 0 elif review_check: return 1 elif not review_check: return 2 def checkPermissionReviewConsultation(self): """ Check for reviewing the Consultation. """ return self.checkPermission(PERMISSION_REVIEW_CONSULTATION) def checkPermissionManageConsultation(self): """ Check for managing the Consultation. """ return self.checkPermission(PERMISSION_MANAGE_CONSULTATION) def checkPermissionViewConsultation(self): """ Check for managing the Consultation. """ return self.checkPermission(PERMISSION_VIEW_CONSULTATION) security.declareProtected(view, 'get_reviews') def get_reviews(self): """ Returns a list with all the Consultation Review objects """ return self.objectValues(['Consultation Review']) def count_line_comments(self): """ Returns the total count of line comments in all reviews """ reviews = self.get_reviews() count = 0 if reviews: for review in reviews: if self.review_has_comments(review): count = count + 1 return count def count_additional_files(self): """ Returns the total count of additional files in all reviews """ reviews = self.get_reviews() count = 0 if reviews: for review in reviews: if review.size > 0: count = count + 1 return count def count_question_answers(self): """ Returns (question_id, answer_count) """ reviews = self.get_reviews() questions = self.get_questions() count = {} for qid, q in questions: count[qid] = 0 for review in reviews: for qid, answer in review.answers: if answer: count[qid] = count[qid] + 1 return count.items() security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'addQuestion') def addQuestion(self, question_body, lang, sortorder, REQUEST=None): """ """ id = 'q%s' % self.utGenRandomId(4) try: sortorder = int(sortorder) except: sortorder = 100 if not self.questions.has_key(id): id = id else: id = id + self.utGenRandomId() self.questions[id] = question_item(question_body, lang, sortorder) self._p_changed = 1 return REQUEST.RESPONSE.redirect('%s/manage_questions_html' % (self.absolute_url(), )) security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'delete_question') def delete_question(self, qid, REQUEST=None): """ """ del (self.questions[qid]) self._p_changed = 1 return REQUEST.RESPONSE.redirect('%s/manage_questions_html' % (self.absolute_url(), )) security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'edit_question') def edit_question(self, qid, question_body, lang, REQUEST=None): """ """ self.questions[qid].save_properties(question_body, lang) self._p_changed = 1 return REQUEST.RESPONSE.redirect('%s/question_edit_html?qid=%s' % (self.absolute_url(), qid)) security.declareProtected(PERMISSION_REVIEW_CONSULTATION, 'get_questions') def get_questions(self): """ Returns the questions sorted by sortorder (question_id, question_item)""" question_items = self.questions.items() question_items.sort(lambda x, y: cmp(x[1].sortorder, y[1].sortorder)) return question_items security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'getQuestionById') def getQuestionById(self, qid): """ Returns the question item for the given id""" return self.questions[qid] security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'changeSortorder') def changeSortorder(self, qid, sortorder): """ """ self.getQuestionById(qid).set_sortorder(sortorder) self._p_changed = 1 security.declareProtected(view, 'getQuestionBody') def getQuestionBody(self, qid, lang): """ Returns the question's body string for the specified language """ return self.getQuestionById(qid).get_body(lang) security.declareProtected(view, 'getQuestionSortorder') def getQuestionSortorder(self, qid): """ """ return self.getQuestionById(qid).get_sortorder() security.declareProtected(view, 'review_has_comments') def review_has_comments(self, review): """ Checks if the review has any line comments """ try: return review.linecomments[0]['comment'] except KeyError: return '' security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'comment_image') comment_image = ImageFile('www/consultation-comment.gif', globals()) #Consultation statistics security.declareProtected(view, 'getRatingTitles') def getRatingTitles(self): """ """ cns_ratings = [x.title for x in self.getRateLists()] return cns_ratings security.declareProtected(view, 'getQuestionsReviews') def getQuestionsReviews(self): """ Returns a dictionary with question ids as keys and a list of reviews that answered to that question as values. {qid: [rating1, rating2, ]} """ reviews = self.get_reviews() questions = self.get_questions() qs_rev = {} for qid, q in questions: qs_rev[qid] = [] for review in reviews: for qid, answer in review.answers: if answer: qs_rev[qid].append(review.getId()) return qs_rev security.declareProtected(PERMISSION_VIEW_CONSULTATION, 'getReviewById') def getReviewById(self, rid): """ """ reviews = self.get_reviews() for review in reviews: if review.getId() == rid: return review #reviews sorting security.declareProtected(PERMISSION_VIEW_CONSULTATION, 'sort_cns_reviews') def sort_cns_reviews(self, by='Date'): """ Selects whitch method to use for sorting """ if by == 'Date': return self.utSortObjsListByMethod(self.get_reviews(), 'get_review_date', 1) else: return self.get_reviews_sorted(by) security.declareProtected(PERMISSION_VIEW_CONSULTATION, 'get_reviews_sorted') def get_reviews_sorted(self, rating=''): """ Returns the list of reviews sorted by rating value for the given rating """ if rating not in self.getRatingTitles(): return self.sort_reviews_page() reviews = [x for x in self.get_reviews()] reviews.sort(lambda x, y: cmp(int(y.getRatings()[rating]), int(x.getRatings()[rating]))) return reviews security.declareProtected(PERMISSION_VIEW_CONSULTATION, 'sort_reviews_page') def sort_reviews_page(self, by='Date', REQUEST=None): """ Open the reviews page sorted acording to 'by' """ if REQUEST is not None: return REQUEST.RESPONSE.redirect('%s/reviews_index_html?by=%s' % (self.absolute_url(), by)) #site pages security.declareProtected(PERMISSION_REVIEW_CONSULTATION, 'edit_review') def edit_review(self): """ """ auth_user = self.REQUEST.AUTHENTICATED_USER.getUserName() for review in self.objectValues(['Consultation Review']): if review.contributor == auth_user: return self.REQUEST.RESPONSE.redirect('%s/edit_html' % review.absolute_url()) self.setSessionErrors(['You cannot edit that Review.']) return self.REQUEST.RESPONSE.redirect(self.absolute_url() + '/index_html') security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'question_edit_html') question_edit_html = PageTemplateFile('zpt/question_edit', globals()) security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'admin_ratelist_html') admin_ratelist_html = PageTemplateFile('zpt/admin_ratelist', globals()) security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'admin_ratelists_html') admin_ratelists_html = PageTemplateFile('zpt/admin_ratelists', globals()) security.declareProtected(PERMISSION_REVIEW_CONSULTATION, 'review_add_html') review_add_html = PageTemplateFile('zpt/review_add', globals()) security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'manage_questions_html') manage_questions_html = PageTemplateFile('zpt/manage_questions', globals()) security.declareProtected(PERMISSION_VIEW_CONSULTATION, 'reviews_index_html') reviews_index_html = PageTemplateFile('zpt/reviews_index', globals()) security.declareProtected(view, 'index_html') index_html = PageTemplateFile('zpt/consultation_index', globals()) security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'edit_html') edit_html = PageTemplateFile('zpt/consultation_edit', globals()) security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'view_statistics_html') view_statistics_html = PageTemplateFile('zpt/view_statistics', globals()) security.declareProtected(PERMISSION_MANAGE_CONSULTATION, 'instructions_html') instructions_html = PageTemplateFile('zpt/instructions', globals())
class NyTalkBackConsultation(Implicit, NyContentData, NyContentType, NyAttributes, NyProperties, NyRoleManager, NyContainer, NyNonCheckControl, utils, NyFolderBase): """ """ meta_type = METATYPE_TALKBACKCONSULTATION meta_label = LABEL_OBJECT meta_types = [ { 'name': METATYPE_TALKBACKCONSULTATION_SECTION, 'action': 'addSection', 'permission': PERMISSION_MANAGE_TALKBACKCONSULTATION }, ] icon = 'misc_/NaayaContent/NyTalkBackConsultation.gif' icon_marked = 'misc_/NaayaContent/NyTalkBackConsultation_marked.gif' security = ClassSecurityInfo() edit_access = NyAccess( 'edit_access', { PERMISSION_REVIEW_TALKBACKCONSULTATION: "Submit comments", PERMISSION_MANAGE_TALKBACKCONSULTATION: "Administer consultation", PERMISSION_INVITE_TO_TALKBACKCONSULTATION: "Send invitations", }) section_sort_order = tuple() def __init__(self, id, contributor): """ """ self.id = id self.contributor = contributor NyContainer.__dict__['__init__'](self) NyProperties.__dict__['__init__'](self) self.invitations = InvitationsContainer('invitations') self.submitted = 1 def set_allow_reviewer_invites(self, allow): perm = '_Naaya___Invite_to_TalkBack_Consultation_Permission' roles = getattr(self, perm, []) if allow and 'Reviewer' not in roles: new_roles = roles + ['Reviewer'] elif not allow and 'Reviewer' in roles: new_roles = tuple(role for role in roles if role != 'Reviewer') else: new_roles = roles if new_roles: setattr(self, perm, new_roles) else: if hasattr(self, perm): delattr(self, perm) def get_allow_reviewer_invites(self): perm = '_Naaya___Invite_to_TalkBack_Consultation_Permission' roles = getattr(self, perm, []) return ('Reviewer' in roles) allow_reviewer_invites = property(get_allow_reviewer_invites, set_allow_reviewer_invites) security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION, 'saveProperties') def saveProperties(self, REQUEST=None, **kwargs): """ """ if not self.checkPermissionEditObject(): raise EXCEPTION_NOTAUTHORIZED(EXCEPTION_NOTAUTHORIZED_MSG) if REQUEST is not None: schema_raw_data = dict(REQUEST.form) else: schema_raw_data = kwargs _lang = schema_raw_data.pop('_lang', schema_raw_data.pop('lang', None)) _releasedate = self.process_releasedate( schema_raw_data.pop('releasedate', ''), self.releasedate) form_errors = self.process_submitted_form( schema_raw_data, _lang, _override_releasedate=_releasedate) if not form_errors: self._p_changed = True self.recatalogNyObject(self) # log date contributor = self.REQUEST.AUTHENTICATED_USER.getUserName() auth_tool = self.getAuthenticationTool() auth_tool.changeLastPost(contributor) notify(NyContentObjectEditEvent(self, contributor)) if REQUEST: self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES, date=self.utGetTodayDate()) REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' % (self.absolute_url(), _lang)) else: if REQUEST is not None: self._prepare_error_response(REQUEST, form_errors, schema_raw_data) REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' % (self.absolute_url(), _lang)) else: raise ValueError(form_errors.popitem()[1]) # pick an error security.declareProtected(view, 'get_consultation') def get_consultation(self): return self security.declareProtected(view, 'list_sections') def list_sections(self): """ """ metatypes = [METATYPE_TALKBACKCONSULTATION_SECTION] sections = dict(self.objectItems(metatypes)) output = [] for section_id in self.section_sort_order: if section_id in sections: output.append(sections.pop(section_id)) output.extend( sorted(sections.values(), key=operator.attrgetter('title'))) return output security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION, 'save_sort_order') def save_sort_order(self, sort_section_id, REQUEST=None): """ save the sort order of sections """ self.section_sort_order = tuple(sort_section_id) if REQUEST is not None: REQUEST.RESPONSE.redirect(self.absolute_url()) _comments_atom = NaayaPageTemplateFile('zpt/comments_atom', globals(), 'tbconsultation_comments_atom') security.declareProtected(view, 'comments_atom') def comments_atom(self, REQUEST=None, days=2): """ ATOM feed with consultation comments """ if isinstance(days, basestring): try: days = int(days) except: days = 2 cutoff = DateTime() - days comments_list = [] for section in self.list_sections(): for paragraph in section.get_paragraphs(): for comment in paragraph.get_comments(): if comment.comment_date < cutoff: continue comments_list.append(comment) comments_list.sort(key=operator.attrgetter('comment_date'), reverse=True) if comments_list: feed_updated = comments_list[0].comment_date else: feed_updated = DateTime() def atom_date_format(date): d = DT2dt(date).strftime('%Y-%m-%dT%H:%M:%S%z') return d[:-2] + ':' + d[-2:] if REQUEST is not None: REQUEST.RESPONSE.setHeader('Content-Type', 'application/atom+xml') return self._comments_atom(comments_list=comments_list, atom_date_format=atom_date_format, feed_updated=feed_updated) security.declareProtected(view, 'get_start_date') def get_start_date(self): """ Returns the start date in dd/mm/yyyy string format. """ return self.utConvertDateTimeObjToString(self.start_date) security.declareProtected(view, 'get_end_date') def get_end_date(self): """ Returns the end date in dd/mm/yyyy string format. """ return self.utConvertDateTimeObjToString(self.end_date) security.declareProtected(view, 'get_days_left') def get_days_left(self): """ Returns the remaining days for the consultation or the number of days before it starts """ today = self.utGetTodayDate().earliestTime() if not self.start_date or not self.end_date: return (1, 0) after_end_date = self.end_date + 1 if self.start_date.lessThanEqualTo(today): return (1, int(str(after_end_date - today).split('.')[0])) else: return (0, int(str(self.start_date - today).split('.')[0])) security.declareProtected(view_management_screens, 'manage_options') def manage_options(self): """ """ l_options = (NyContainer.manage_options[0], ) l_options += ({'label': 'View', 'action': 'index_html'},) + \ NyContainer.manage_options[3:8] return l_options security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION, 'delete_sections') def delete_sections(self, del_section_id, REQUEST=None): """ remove the specified sections """ self.manage_delObjects(list(del_section_id)) self.setSessionInfoTrans('Removed ${count} sections.', count=str(len(del_section_id))) if REQUEST is not None: REQUEST.RESPONSE.redirect(self.absolute_url()) def get_user_name(self): # first, check if we have an invite key invitation = self.invitations.get_current_invitation(self.REQUEST) if invitation is not None: return invitation.name # no invite key; look for current Zope user auth_tool = self.getAuthenticationTool() userid = auth_tool.get_current_userid() if userid is None: # anonymous user return None name = auth_tool.name_from_userid(userid) if name == '': name = userid return name def get_user_name_or_userid(self, userid=None): if userid is None: return self.get_user_name() auth_tool = self.getAuthenticationTool() name = auth_tool.name_from_userid(userid) if name == '': name = userid return name def checkTalkBackConsultationUser(self): """ Checks if the user is logged in and has reviewer rights: 0 if user is anonymous, 1 if user has reviewer role 2 if user doesn't have reviewer role """ review_check = self.checkPermissionReviewTalkBackConsultation() if self.isAnonymousUser(): return 0 elif review_check: return 1 elif not review_check: return 2 security.declareProtected(view, 'check_cannot_comment') def check_cannot_comment(self): """ """ if not self.checkPermissionReviewTalkBackConsultation(): if self.isAnonymousUser(): return 'not-logged-in' else: return 'no-permission' if self.get_days_left()[1] <= 0 and not ( self.checkPermissionManageTalkBackConsultation() or self.checkPermissionReviewTalkBackConsultationAfterDeadline()): return 'deadline-reached' security.declareProtected(PERMISSION_COMMENTS_ADD, 'log_in_authenticated') def log_in_authenticated(self, REQUEST=None): """ Log in user and redirect to TalkBack Consultation index """ if REQUEST is not None: self.REQUEST.RESPONSE.redirect(self.absolute_url()) # permissions def checkPermissionReviewTalkBackConsultation(self): """ Check for reviewing the TalkBack Consultation. """ return self.checkPermission(PERMISSION_REVIEW_TALKBACKCONSULTATION) security.declareProtected( PERMISSION_REVIEW_TALKBACKCONSULTATION_AFTER_DEADLINE, 'review_after_deadline') def review_after_deadline(self): """ Dummy function to register the permission. """ raise NotImplementedError def checkPermissionReviewTalkBackConsultationAfterDeadline(self): """ Check for reviewing the TalkBack Consultation after the deadline has passed. """ return self.checkPermission( PERMISSION_REVIEW_TALKBACKCONSULTATION_AFTER_DEADLINE) def checkPermissionManageTalkBackConsultation(self): """ Check for managing the TalkBack Consultation. """ return self.checkPermission(PERMISSION_MANAGE_TALKBACKCONSULTATION) def checkPermissionInviteToTalkBackConsultation(self): """ Check for inviting others to the TalkBack Consultation. """ return self.checkPermission(PERMISSION_INVITE_TO_TALKBACKCONSULTATION) def own_comments(self): """ Check if the current user has any comments on the consultation """ return [ comment for comment in self.admin_comments._all_comments() if comment['comment'].contributor == self.REQUEST.AUTHENTICATED_USER.getUserName() ] security.declareProtected(view, 'custom_editor') def custom_editor(self, editor_tool, lang, dom_id): extra_options = { 'content_css': self.absolute_url() + '/misc_/NaayaContent/tb-editor.css', 'theme_advanced_buttons1': 'bold,italic,underline,strikethrough,sub,sup,forecolor,' 'backcolor,removeformat,separator,' 'bullist,numlist,separator,' 'justifyleft,justifycenter,justifyright,justifyfull,separator,' 'link,unlink,hr,image,separator,' 'pastetext,pasteword,cleanup,code,help', 'theme_advanced_buttons2': '', } return editor_tool.render(dom_id, lang, image_support=True, extra_options=extra_options) security.declareProtected(view, 'get_files') def get_files(self): """ Get a list of all files attached to the consultation""" return [ob for ob in self.objectValues('Naaya Blob File')] security.declareProtected(view, 'findUsers') def findUsers(self, search_param, search_term): """ """ if len(search_term) == 0: return [] return json.dumps(findUsers(self.getSite(), search_param, search_term)) addSection = addSection # zmi pages security.declareProtected(view_management_screens, 'manage_edit_html') manage_edit_html = PageTemplateFile('zpt/talkbackconsultation_manage_edit', globals()) # site pages security.declareProtected(view, 'index_html') index_html = NaayaPageTemplateFile('zpt/talkbackconsultation_index', globals(), 'tbconsultation_index') # standard_template_macro, header and footer templates are proxied # since invited reviewers have "View" permission only in this folder; # if the consultation is restricted, they would not be able to see # consultation pages. def standard_html_header(self, *args, **kwargs): return self.aq_parent.standard_html_header(*args, **kwargs) def standard_html_footer(self, *args, **kwargs): return self.aq_parent.standard_html_footer(*args, **kwargs) def standard_template_macro(self, *args, **kwargs): return self.aq_parent.standard_template_macro(*args, **kwargs) security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION, 'edit_html') edit_html = NaayaPageTemplateFile('zpt/talkbackconsultation_edit', globals(), 'tbconsultation_edit') security.declareProtected(PERMISSION_MANAGE_TALKBACKCONSULTATION, 'section_add_html') section_add_html = addSection_html __allow_groups__ = InvitationUsersTool() _View_Permission = ['InvitedReviewer'] _Naaya___Review_TalkBack_Consultation_Permission = ['InvitedReviewer'] __ac_roles__ = ['InvitedReviewer'] admin_comments = CommentsAdmin('admin_comments')
class NySimpleConsultation(NyAttributes, Implicit, NyProperties, BTreeFolder2, NyContainer, NyCheckControl, NyValidation, utils): """ """ meta_type = METATYPE_OBJECT meta_label = LABEL_OBJECT all_meta_types = () icon = 'misc_/NaayaContent/NySimpleConsultation.gif' icon_marked = 'misc_/NaayaContent/NySimpleConsultation_marked.gif' title = LocalProperty('title') description = LocalProperty('description') security = ClassSecurityInfo() edit_access = NyAccess( 'edit_access', { PERMISSION_REVIEW_SIMPLECONSULTATION: "Submit comments", PERMISSION_MANAGE_SIMPLECONSULTATION: "Administer consultation", }) def __init__(self, id, title, description, sortorder, start_date, end_date, public_registration, allow_file, contributor, releasedate, lang): """ """ self.id = id NyValidation.__dict__['__init__'](self) NyCheckControl.__dict__['__init__'](self) NyContainer.__dict__['__init__'](self) BTreeFolder2.__init__(self) self.contributor = contributor try: del self.title except: pass self.save_properties(title, description, sortorder, start_date, end_date, public_registration, allow_file, releasedate, lang) NyProperties.__dict__['__init__'](self) self.submitted = 1 security.declarePrivate('save_properties') def save_properties(self, title, description, sortorder, start_date, end_date, public_registration, allow_file, releasedate, lang): self._setLocalPropValue('title', lang, title) self._setLocalPropValue('description', lang, description) if not hasattr(self, 'imageContainer'): self.imageContainer = NyImageContainer(self, True) if start_date: self.start_date = self.utConvertStringToDateTimeObj(start_date) else: self.start_date = self.utGetTodayDate() if end_date: self.end_date = self.utConvertStringToDateTimeObj(end_date) else: self.end_date = self.utGetTodayDate() try: self.sortorder = abs(int(sortorder)) except: self.sortorder = DEFAULT_SORTORDER self.releasedate = releasedate self.public_registration = public_registration self.allow_file = allow_file security.declareProtected(PERMISSION_MANAGE_SIMPLECONSULTATION, 'saveProperties') def saveProperties(self, title='', description='', sortorder='', start_date='', end_date='', public_registration='', allow_file='', file='', lang='', REQUEST=None): """ """ if not title: self.setSession('title', title) self.setSession('description', description) self.setSessionErrors(['The Title field must have a value.']) if REQUEST: return REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' % (self.absolute_url(), lang)) else: raise ValueError('The title field must have a value.') if file and not file.read(): self.setSession('title', title) self.setSession('description', description) self.setSessionErrors(['File must not be empty']) return REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' % (self.absolute_url(), lang)) exfile = self.get_exfile() if file and exfile: exfile.saveUpload(file=file, lang=lang) downloadfilename = file.filename exfile._setLocalPropValue('downloadfilename', lang, downloadfilename) elif file and not exfile: addNyExFile(self, title=title, file=file, lang=lang, source='file') releasedate = self.releasedate self.updateRequestRoleStatus(public_registration, lang) self.save_properties(title, description, sortorder, start_date, end_date, public_registration, allow_file, releasedate, lang) if REQUEST: self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES, date=self.utGetTodayDate()) REQUEST.RESPONSE.redirect('%s/edit_html?lang=%s' % (self.absolute_url(), lang)) security.declareProtected(PERMISSION_MANAGE_SIMPLECONSULTATION, 'updateRequestRoleStatus') def updateRequestRoleStatus(self, public_registration, lang): """ Allow public registration for this consultation """ if public_registration: self.updateDynamicProperties( self.processDynamicProperties( METATYPE_OBJECT, {'show_contributor_request_role': 'on'}), lang) if not public_registration: self.updateDynamicProperties( self.processDynamicProperties( METATYPE_OBJECT, {'show_contributor_request_role': ''}), lang) security.declareProtected(PERMISSION_MANAGE_SIMPLECONSULTATION, 'checkReviewerRole') def checkReviewerRole(self): """ Checks if the 'Reviewer' role exists, creates and adds review permissions if it doesn't exist """ auth_tool = self.getAuthenticationTool() roles = auth_tool.list_all_roles() PERMISSION_GROUP = 'Review content' if 'Reviewer' not in roles: auth_tool.addRole('Reviewer', [PERMISSION_REVIEW_SIMPLECONSULTATION]) else: permission_add_role(self, PERMISSION_REVIEW_SIMPLECONSULTATION, 'Reviewer') #give permissions to administrators admin_permissions = self.permissionsOfRole('Administrator') site = self.getSite() if PERMISSION_MANAGE_SIMPLECONSULTATION not in admin_permissions: site.manage_permission(PERMISSION_MANAGE_SIMPLECONSULTATION, ('Administrator', ), acquire=1) site.manage_permission(PERMISSION_REVIEW_SIMPLECONSULTATION, ('Administrator', ), acquire=1) security.declareProtected(view, 'get_exfile') def get_exfile(self): """ Returns the first ExFile in the Simple Consultation, there should be only one. """ try: exfile = self.objectValues(['Naaya Extended File'])[0] except IndexError: exfile = None return exfile security.declareProtected(view, 'check_exfile_for_lang') def check_exfile_for_lang(self, lang): """ Checks if there is a file uploaded for the given language. """ return self.get_exfile().getFileItem(lang).size > 0 security.declareProtected(view, 'get_exfile_langs') def get_exfile_langs(self): """ Returns the languages for witch NyExFile contains files. """ return [ language for language in self.getSite().gl_get_languages_map() if self.check_exfile_for_lang(language['id']) ] security.declareProtected(view, 'get_start_date') def get_start_date(self): """ Returns the start date in dd/mm/yyyy string format. """ return self.utConvertDateTimeObjToString(self.start_date) security.declareProtected(view, 'get_end_date') def get_end_date(self): """ Returns the end date in dd/mm/yyyy string format. """ return self.utConvertDateTimeObjToString(self.end_date) security.declareProtected(view, 'get_days_left') def get_days_left(self): """ Returns the remaining days for the consultation or the number of days before it starts """ today = self.utGetTodayDate().earliestTime() if not self.start_date or not self.end_date: return (1, 0) if self.start_date.lessThanEqualTo(today): return (1, int(str(self.end_date - today).split('.')[0])) else: return (0, int(str(self.start_date - today).split('.')[0])) security.declareProtected(view_management_screens, 'manage_options') def manage_options(self): """ """ l_options = (NyContainer.manage_options[0], ) l_options += ({ 'label': 'View', 'action': 'index_html' }, ) + NyContainer.manage_options[3:8] return l_options security.declareProtected(view, 'check_contributor_comment') def check_contributor_comment(self, contributor='', REQUEST=None): """ Returns True if user already posted a comment """ if not contributor and REQUEST: contributor = REQUEST.AUTHENTICATED_USER.getUserName() return contributor in [ comment.contributor for comment in self.objectValues(['Simple Consultation Comment']) ] security.declareProtected(PERMISSION_REVIEW_SIMPLECONSULTATION, 'addComment') def addComment(self, title='', contributor_name='', message='', file='', REQUEST=None): """ """ if not title or not contributor_name or not message: self.setSession('title', title) self.setSession('contributor_name', contributor_name) self.setSession('message', message) self.setSessionErrors(['Fill in all mandatory fields.']) return REQUEST.RESPONSE.redirect(self.absolute_url() + '/add_simpleconsultation_comment') contributor = REQUEST.AUTHENTICATED_USER.getUserName() if not self.allow_file: file = '' days = self.get_days_left() if days[0] == 1 and days[1] > 0: if not self.check_contributor_comment(contributor): addSimpleConsultationComment(self, title, contributor, contributor_name, message, file, REQUEST) else: return REQUEST.RESPONSE.redirect( self.absolute_url() + '/add_simpleconsultation_comment?status=failed') elif days[0] == 1 and days[1] <= 0: return REQUEST.RESPONSE.redirect( self.absolute_url() + '/add_simpleconsultation_comment?status=late') elif days[0] <= 0: return REQUEST.RESPONSE.redirect( self.absolute_url() + '/add_simpleconsultation_comment?status=soon') def checkSimpleConsultationUser(self): """ Checks if the user is logged in and has reviewer rights: 0 if user is anonymous, 1 if user has reviewer role 2 if user doesn't have reviewer role """ review_check = self.checkPermissionReviewSimpleConsultation() if self.isAnonymousUser(): return 0 elif review_check: return 1 elif not review_check: return 2 #permissions def checkPermissionReviewSimpleConsultation(self): """ Check for reviewing the Simple Consultation. """ return self.checkPermission(PERMISSION_REVIEW_SIMPLECONSULTATION) def checkPermissionManageSimpleConsultation(self): """ Check for managing the Simple Consultation. """ return self.checkPermission(PERMISSION_MANAGE_SIMPLECONSULTATION) #zmi pages security.declareProtected(view_management_screens, 'manage_edit_html') manage_edit_html = PageTemplateFile('zpt/simpleconsultation_manage_edit', globals()) #site pages security.declareProtected(view, 'index_html') index_html = PageTemplateFile('zpt/simpleconsultation_index', globals()) security.declareProtected(PERMISSION_MANAGE_SIMPLECONSULTATION, 'edit_html') edit_html = PageTemplateFile('zpt/simpleconsultation_edit', globals()) security.declareProtected(PERMISSION_REVIEW_SIMPLECONSULTATION, 'add_simpleconsultation_comment') add_simpleconsultation_comment = PageTemplateFile( 'zpt/simpleconsultation_comment_add', globals())
class NyForum(NyRoleManager, NyPermissions, NyForumBase, Folder, utils, LocalPropertyManager): """ """ interface.implements(INyForum) meta_type = METATYPE_NYFORUM meta_label = LABEL_NYFORUM icon = 'misc_/NaayaForum/NyForum.gif' icon_marked = 'misc_/NaayaForum/NyForum_marked.gif' topics_listing = 'Plain table' topics_ordering = 'Reverse: Chronological order' message_top = LocalProperty('message_top') message_outdated = LocalProperty('message_outdated') manage_options = (Folder.manage_options[0:2] + ({ 'label': 'Properties', 'action': 'manage_edit_html' }, ) + Folder.manage_options[3:8]) meta_types = ({ 'name': METATYPE_NYFORUMTOPIC, 'action': 'manage_addNyForumTopic_html' }, ) all_meta_types = meta_types security = ClassSecurityInfo() edit_access = NyAccess( 'edit_access', { view: "Access content", PERMISSION_MODIFY_FORUMTOPIC: "Modify topic", PERMISSION_ADD_FORUMMESSAGE: "Add message", PERMISSION_MODIFY_FORUMMESSAGE: "Modify message", }) #constructors security.declareProtected(view_management_screens, 'manage_addNyForumTopic_html') manage_addNyForumTopic_html = manage_addNyForumTopic_html security.declareProtected(PERMISSION_MODIFY_FORUMTOPIC, 'topic_add_html') topic_add_html = topic_add_html security.declareProtected(PERMISSION_MODIFY_FORUMTOPIC, 'addNyForumTopic') addNyForumTopic = addNyForumTopic def __init__(self, id, title, description, categories, file_max_size, contributor): """ """ self.id = id self.title = title self.description = description self.categories = categories self.file_max_size = file_max_size self.contributor = contributor NyForumBase.__dict__['__init__'](self) #make this object available for portal search engine self.submitted = 1 self.approved = 1 def loadDefaultData(self): """ Sets default permissions """ self.manage_permission(PERMISSION_ADD_FORUMMESSAGE, ['Anonymous'], acquire=1) self.manage_permission(PERMISSION_MODIFY_FORUMTOPIC, ['Administrator', 'Manager'], acquire=1) self.manage_permission(PERMISSION_SKIP_CAPTCHA, ['Administrator', 'Manager'], acquire=1) def __setstate__(self, state): """ For backwards compatibility. """ NyForum.inheritedAttribute("__setstate__")(self, state) if not hasattr(self, 'file_max_size'): self.file_max_size = 0 security.declarePrivate('_get_template') def _get_template(self, name): template = self._getOb('emailpt_%s' % name, None) if template is not None: return template.render_email template = email_templates.get(name, None) if template is not None: return template.render_email raise ValueError('template for %r not found' % name) #api def get_forum_object(self): return self def get_forum_path(self, p=0): return self.absolute_url(p) def get_forum_categories(self): return self.categories def get_topics(self): return self.objectValues(METATYPE_NYFORUMTOPIC) def count_topics(self): return len(self.objectIds(METATYPE_NYFORUMTOPIC)) def getObjectsForValidation(self): return [] def count_notok_objects(self): return 0 def count_notchecked_objects(self): return 0 security.declarePrivate('processIdentity') def processIdentity(self): """ Returns information about the user who created the topic/message and the posting date. """ return self.REQUEST.AUTHENTICATED_USER.getUserName( ), self.utGetTodayDate() security.declarePrivate('handleAttachmentUpload') def handleAttachmentUpload(self, ob, file): """ Handle upload of a file. A B{File} object will be created inside the B{given} object. """ if file != '': if hasattr(file, 'filename'): if file.filename != '': if file.filename.find('\\') != -1: id = file.filename.split('\\')[-1] else: id = file.filename #check file size id = self.utSlugify(id) if len(file.read() ) <= self.file_max_size or self.file_max_size == 0: ob.manage_addFile(id=id, file=file) def can_be_seen(self): """ Indicates if the current user has access to the current forum. """ return self.checkPermission(view) def has_restrictions(self): """ Indicates if this folder has restrictions for the current user. """ return not self.acquiredRolesAreUsedBy(view) def get_roles_with_access(self): """ Returns a list of roles that have access to this forum. """ r = [] ra = r.append for x in self.rolesOfPermission(view): if x['selected'] and x['name'] not in [ 'Administrator', 'Anonymous', 'Manager', 'Owner' ]: ra(x['name']) return r security.declarePublic('getPublishedFolders') def getPublishedFolders(self): if not self.checkPermissionView(): return [] return self.objectValues(METATYPE_NYFORUMTOPIC) def getPublishedObjects(self): return [] def getObjects(self): return self.getPublishedFolders() def getPendingFolders(self): return [] def getFolders(self): return self.getPublishedFolders() def hasContent(self): return (len(self.getObjects()) > 0) def get_sort_options(self): """ return a maping of sorting options""" return [['Subject', 'subject', False], ['Access type', 'access', False], ['Status', 'status', False], ['Author', 'author', False], ['Number of replies', 'count_messages', False], ['Number of views', 'views', False], ['Chronological order', 'last_message', False], ['Reverse: Subject', 'subject', True], ['Reverse: Access type', 'access', True], ['Reverse: Status', 'status', True], ['Reverse: Author', 'author', True], ['Reverse: Number of replies', 'count_messages', True], ['Reverse: Number of views', 'views', True], ['Reverse: Chronological order', 'last_message', True]] security.declareProtected(view, 'checkTopicsPermissions') def checkTopicsPermissions(self): """ This function is called on the forum index and it checkes whether or not to display the various buttons on that form. Returns in a list of tuples: which buttons should be visible, a list of topics, sorted reversed by the date of the last post. """ REQUEST = self.REQUEST skey = REQUEST.get('skey', None) rkey = None if skey is None: for option in self.get_sort_options(): if self.topics_ordering == option[0]: skey = option[1] rkey = option[2] if rkey is None: rkey = REQUEST.get('rkey') if not rkey: rkey = False else: rkey = rkey not in ['0', 'False'] if self.topics_listing == 'Plain table': topics = {'Plain table': []} else: topics = {} for category in self.categories: topics[category] = [] btn_select, btn_delete, can_operate = 0, 0, 0 # btn_select - if there is at least one permisson to delete or copy an object # btn_delete - if there is at least one permisson to delete an object for x in self.objectValues(METATYPE_NYFORUMTOPIC): del_permission = x.checkPermissionModifyForumTopic() edit_permission = x.checkPermissionModifyForumTopic() if del_permission: btn_select = 1 if del_permission: btn_delete = 1 if edit_permission: can_operate = 1 if self.topics_listing == 'Plain table': topics['Plain table'].append( (del_permission, edit_permission, x)) else: if x.category in topics.keys(): topics[x.category].append( (del_permission, edit_permission, x)) elif 'Other' in topics.keys(): topics['Other'].append( (del_permission, edit_permission, x)) else: topics['Other'] = [(del_permission, edit_permission, x)] can_operate = can_operate or btn_select for topics_category in topics.values(): if skey == 'subject': topics_category.sort(key=lambda x: x[2].title_or_id().lower(), reverse=rkey) elif skey == 'access': topics_category.sort(key=lambda x: x[2].access_type(), reverse=rkey) elif skey == 'status': topics_category.sort(key=lambda x: x[2].is_topic_opened(), reverse=rkey) elif skey == 'views': topics_category.sort( key=lambda x: self.getTopicHits(topic=x[2].id), reverse=rkey) elif skey == 'last_message': topics_category.sort( key=lambda x: x[2].get_last_message().postdate, reverse=rkey) else: try: topics_category.sort(key=lambda x: getattr(x[2], skey), reverse=rkey) except AttributeError: #This means the sort key was wrong (manually altered) pass return btn_select, btn_delete, can_operate, topics, skey, rkey def checkPermissionSkipCaptcha(self): return getSecurityManager().checkPermission('Naaya - Skip Captcha', self) #zmi actions security.declareProtected(view_management_screens, 'manageProperties') def manageProperties(self, title='', description='', categories='', file_max_size='', topics_listing='', topics_ordering='', REQUEST=None): """ """ contributor = self.REQUEST.AUTHENTICATED_USER.getUserName() self.contributor = contributor self.title = title self.description = description self.categories = self.utConvertLinesToList(categories) self.file_max_size = abs(int(file_max_size)) self.topics_listing = topics_listing self.topics_ordering = topics_ordering self._p_changed = 1 if REQUEST: REQUEST.RESPONSE.redirect('manage_edit_html?save=ok') #zmi actions security.declareProtected(PERMISSION_ADD_FORUM, 'saveProperties') def saveProperties(self, title='', description='', categories='', file_max_size='', topics_listing='', topics_ordering='', message_top='', message_outdated='', alphabetic_categories=None, REQUEST=None): """ """ contributor = self.REQUEST.AUTHENTICATED_USER.getUserName() self.contributor = contributor self.title = title self.description = description self.categories = self.utConvertLinesToList(categories) self.file_max_size = abs(int(file_max_size)) self.topics_listing = topics_listing self.topics_ordering = topics_ordering lang = self.gl_get_selected_language() self._setLocalPropValue('message_top', lang, message_top) self._setLocalPropValue('message_outdated', lang, message_outdated) self.alphabetic_categories = alphabetic_categories self._p_changed = 1 if REQUEST: self.setSessionInfoTrans(MESSAGE_SAVEDCHANGES, date=self.utGetTodayDate()) REQUEST.RESPONSE.redirect('edit_html?save=ok') #site actions security.declareProtected(PERMISSION_MODIFY_FORUMTOPIC, 'deleteTopics') def deleteTopics(self, ids='', REQUEST=None): """ """ try: self.manage_delObjects(self.utConvertToList(ids)) except: self.setSessionErrorsTrans('Error while deleting data.') else: self.setSessionInfoTrans('Topic(s) deleted.') if REQUEST: REQUEST.RESPONSE.redirect('%s/index_html' % self.absolute_url()) # # Statistics # security.declarePrivate("_getStatisticsContainerCursor") def _getStatisticsContainerCursor(self): """ Create statistics container if it doesn't exists and return it """ stats_container = getattr(self, STATISTICS_CONTAINER, None) if stats_container is None: # do DB was ever created cursor = None else: try: cursor = stats_container.cursor() except naaya.sql.DbMissing: # DB was removed cursor = None if cursor is None: stats_container = naaya.sql.new_db() setattr(self, STATISTICS_CONTAINER, stats_container) table = ("CREATE TABLE HITS" "(id INTEGER PRIMARY KEY ASC AUTOINCREMENT") for (col, val) in STATISTICS_COLUMNS.items(): table += ", " + col + " " + val table += ")" cursor = stats_container.cursor() cursor.execute(table) return cursor def _removeStatisticsContainer(self): """ Remove statistics container if exists """ stats_container = getattr(self, STATISTICS_CONTAINER, None) if stats_container is not None: if hasattr(stats_container, 'drop'): stats_container.drop() delattr(self, STATISTICS_CONTAINER) security.declareProtected(view, 'getTopicHits') def getTopicHits(self, topic): """ Returns statistics for given topic """ cursor = self._getStatisticsContainerCursor() cursor.execute("SELECT hits from HITS where topic=?", (topic, )) res = cursor.fetchone() if not res: cursor.execute("INSERT into HITS(topic) values(?)", (topic, )) return 0 else: return res[0] security.declarePrivate('setTopicHits') def setTopicHits(self, topic, how_many=1): hits = self.getTopicHits(topic) + how_many cursor = self._getStatisticsContainerCursor() cursor.execute("UPDATE HITS set hits=? where topic=?", (hits, topic)) security.declareProtected(view, 'updateTopicHits') def updateTopicHits(self, topic): """ Update hits for topic """ self.setTopicHits(topic, 1) security.declareProtected(view, 'removeTopicHits') def removeTopicHits(self, topic): """ Remove hits record for topic """ cursor = self._getStatisticsContainerCursor() cursor.execute("DELETE FROM HITS where topic=?", (topic, )) security.declareProtected(view, 'hasVersion') def hasVersion(self): """ """ return False security.declarePublic('export_this') def export_this(self, folderish=0): """ """ return '' security.declareProtected(view, 'get_categories') def get_categories(self): """ return categories, sorted if the option is set on the forum """ if getattr(self, 'alphabetic_categories', None): return sorted(self.categories) return self.categories #zmi pages security.declareProtected(view_management_screens, 'manage_edit_html') manage_edit_html = PageTemplateFile('zpt/forum_manage_edit', globals()) #site pages security.declareProtected(view, 'index_html') index_html = NaayaPageTemplateFile('zpt/forum_index', globals(), 'forum_index') security.declareProtected(view, 'messages_feed') messages_feed = messages_feed security.declareProtected(PERMISSION_ADD_FORUM, 'edit_html') edit_html = PageTemplateFile('zpt/forum_edit', globals()) security.declareProtected(PERMISSION_ADD_FORUM, 'forum_add_html') forum_add_html = PageTemplateFile('zpt/forum_add', globals())