# -*- coding: utf-8 # $Id$ # Copyright 2001, 2002 by IVA Team and contributors # # This file is part of IVA. # # IVA is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # IVA is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with IVA; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """Contains class CourseManager, which acts as a factory object for Courses and also the container for the courses.""" __version__ = '$Revision$'[11:-2] import re, string, time import strptime import OFS, Globals, AccessControl from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2 from Globals import Persistent, PersistentMapping import types from Products.ZCatalog.ZCatalog import ZCatalog # from TraversableWrapper import TraversableWrapper as TW from TraversableWrapper import Traversable from Course import Course from common import quote_html_hack, make_action from common import perm_view, perm_edit, perm_manage, perm_add_lo, perm_access,\ roles_admin, roles_staff, roles_user, translate from input_checks import is_valid_title from Thread import Thread from AccessControl import ClassSecurityInfo from Cruft import Cruft from common import course_level_roles from common import roles_teacher, roles_tutor, roles_student import time class IDManager(Thread): security = ClassSecurityInfo() def __init__(self): self.__id_counter = 0L # Overrides generate_id from Thread! security.declarePrivate('generate_id') def generate_id(self): """Return a probably random integer.""" self.__id_counter += 1L return str(self.__id_counter) # CourseManager exists in FLE/courses and contains all the courses # that the FLE installation holds. class CourseManager( BTreeFolder2, Traversable, Cruft, Persistent, AccessControl.Role.RoleManager, OFS.SimpleItem.Item, IDManager, ): """FLE Coursemanager.""" meta_type = 'CourseManager' security = ClassSecurityInfo() security.declareObjectPublic() # No additional comments. def __init__(self, id): """Construct Course manager object.""" self.id = id BTreeFolder2.__init__(self, id) self.title = '' self.cCategories = PersistentMapping() self.cCategories['groups'] = {} IDManager.__init__(self) for role in course_level_roles: self._addRole(role) catalog = ZCatalog('catalog_notes', 'ZCatalog for notes') # indexes catalog.addIndex('get_subject', 'TextIndex') catalog.addIndex('get_body', 'TextIndex') catalog.addIndex('get_author', 'FieldIndex') catalog.addIndex('get_tt_id', 'FieldIndex') # metadata catalog.addColumn('get_subject') catalog.addColumn('get_author') catalog.addColumn('absolute_url') self._setObject('catalog_notes', catalog) self._p_changed = 1 # ZCatalog for indexing courses. catalog = ZCatalog('courses_zcatalog', 'ZCatalog for courses') # indexes catalog.addIndex('get_courseID','FieldIndex') catalog.addIndex('getCourseCategory','FieldIndex') catalog.addIndex('getStatus','FieldIndex') catalog.addIndex('getRegStatus','FieldIndex') catalog.addIndex('get_all_users_id','FieldIndex') catalog.addIndex('get_end_date','FieldIndex') # XXX: Date index here maybe catalog.addIndex('get_start_date','FieldIndex') # XXX: haven't tested it yet catalog.addIndex('get_n_artefacts','FieldIndex') # XXX: after adding artefact catalog.addIndex('get_n_notes','FieldIndex') # XXX: or note we need to reindex course catalog.addIndex('get_n_users','FieldIndex') catalog.addIndex('get_name','FieldIndex') catalog.addIndex('get_teachers','FieldIndex') catalog.addIndex('lastActive','FieldIndex') # XXX: should be fetch from somewhere else... catalog.addIndex('lastModify','FieldIndex') # XXX catalog.addIndex('meta_type','FieldIndex') catalog.addIndex('getUniqId', 'FieldIndex') # metadata catalog.addColumn('getCourseCategory') catalog.addColumn('getLogoURL') catalog.addColumn('getStatus') catalog.addColumn('getRegStatus') catalog.addColumn('get_all_users_id') catalog.addColumn('get_courseID') catalog.addColumn('get_end_date') catalog.addColumn('get_id') catalog.addColumn('get_n_artefacts') catalog.addColumn('get_n_notes') catalog.addColumn('get_n_users') catalog.addColumn('get_name') catalog.addColumn('get_start_date') catalog.addColumn('get_teachers') catalog.addColumn('lastActive') catalog.addColumn('lastModify') catalog.addColumn('meta_type') catalog.addColumn('getLogoThumbnailURL') self._setObject('courses_zcatalog', catalog) self._p_changed = 1 security.declarePrivate('manage_afterAdd') def manage_afterAdd(self, item, container): """Set default permissions for roles.""" self.manage_permission(perm_access, ('Manager','IVAAdmin','Student','Teacher','Anonymous'), 0) self.manage_permission(perm_edit, ('Manager','IVAAdmin','Teacher'), 0) self.manage_permission(perm_view, ('Manager','IVAAdmin','Teacher','Student'), 0) self.manage_permission(perm_add_lo, ('Manager','IVAAdmin','Teacher'), 0) try: self.manage_permission('Zwiki: Add pages', ('Teacher','Owner',), 0) self.manage_permission('Zwiki: Add wikis', ('Teacher','Owner',), 0) self.manage_permission('Zwiki: Change page types', ('Teacher','Owner',), 0) self.manage_permission('Zwiki: Delete pages', ('Teacher','Owner',), 0) self.manage_permission('Zwiki: Edit pages', ('Teacher','Owner',), 0) self.manage_permission('Zwiki: Rename pages', ('Teacher','Owner',), 0) self.manage_permission('Zwiki: Reparent pages', ('Teacher','Owner',), 0) except ValueError: # we don't have zwiki around pass security.declareProtected(perm_view, 'index_html') def index_html(self, REQUEST=None, **kw): """ index_html """ return self.cm_index_html(userLocation='Management', **kw) def hasLogo(self): return 0 security.declareProtected(perm_add_lo, 'add_course_impl') def add_course_impl(self, teacher, uniq_id=None): """Implementation for add_course.""" if uniq_id is None: suffix = '_'+str(int(time.time())) uniq_id = self.generateId(prefix='course',suffix=suffix,rand_ceiling=99999999999) obj = Course( self, '', # name (teacher,), '', # desc '', # organisation '', # methods '', # starting_date '', # ending_date uniq_id, # uniq_id ) id = obj.id self._setObject(id, obj) return id security.declareProtected(perm_manage, 'add_course_form_handler') def add_course_form_handler( self, REQUEST, course_id, my_name, desc, organisation, methods, start_date, end_date, creating_new_course='', do_groupfolder='1', cancel='', # submit buttons add='', # tekst='', logo_upload=None, staatus=0, regStatus=0, cCat = 0, credits='', courseID='' ): """Check user input data. this is for creating courses only for now.""" # return str(self.REQUEST.AUTHENTICATED_USER.getUserName()) if cancel: # cancel button press if creating_new_course: REQUEST.RESPONSE.redirect('index_html') else: REQUEST.RESPONSE.redirect('course_info?course_id=%s' % course_id) return elif not add: raise 'FLE Error', 'Unknown button' if not creating_new_course: raise 'IVA Error', 'Calling add_course_form_handler without creating_new_course attribute' # Ok, add button pressed action=apply( make_action, ['manage_course_info'] + [(x, eval(x)) for x in ('my_name', 'desc', 'organisation', 'methods', 'start_date', 'end_date')]) if course_id: action += '&course_id=' + course_id else: action += '&creating_new_course=1' my_name=my_name.strip() if not is_valid_title(my_name): return self.message_dialog_error( self, REQUEST, title='Invalid name', message='Give valid name', action=action) if creating_new_course and my_name in [x.get_name for x in self.get_courses()]: return self.message_dialog_error( self, REQUEST, title='Invalid name', message="Name '%s' taken" % my_name, action=action) if not creating_new_course \ and my_name != self.get_child(course_id).get_name() \ and my_name in [x.get_name() for x in self.get_courses()]: return self.message_dialog_error( self, REQUEST, title='Invalid name', message="Name '%s' taken" % my_name, action=action) from common import convert_date # convert dates to time.time()-format errors = [] if not start_date: starting_date = 0 else: try: time_tuple = strptime.strptime(start_date, translate(self,'short_date_format',default="%Y-%m-%d",target=self.giveLanguage(REQUEST))) starting_date = convert_date(str(time_tuple[2]), # day str(time_tuple[1]), # month str(time_tuple[0])) # year except: errors.append(translate(self,'Starting date:',target=self.giveLanguage(REQUEST)),) if not end_date: ending_date = 0 else: try: time_tuple = strptime.strptime(end_date, translate(self,'short_date_format',default="%Y-%m-%d",target=self.giveLanguage(REQUEST))) ending_date = convert_date(str(time_tuple[2]), # day str(time_tuple[1]), # month str(time_tuple[0])) # year except: errors.append(translate(self,'Ending date:',target=self.giveLanguage(REQUEST)),) organisation = organisation.strip() if organisation and not is_valid_title(organisation): errors.append(translate(self,'Organization',target=self.giveLanguage(REQUEST))) # desc and methods are not checked because render_description() and # render_methods() methods in Course filter out unwanted HTML tags. if len(errors) > 0: return self.message_dialog_error( self, REQUEST, title='Invalid input', message=translate(self,'Invalid fields',target=self.giveLanguage(REQUEST)) + ": '" + \ "' , '".join(errors) + "'", action=action) # edit an existing course if creating_new_course: # Create new course, then proceed with updating it with # supplied data teacher = '' course_id = self.add_course_impl(teacher) #teacher_obj.user_courselist_cache.append(course_id) logo=None try: #Opera puhul ajab puuduva pildi juures kägu if len(logo_upload.filename)>0: logo=logo_upload.read() else: logo=None except: pass course_obj = self.get_child(course_id) course_obj.update( my_name, desc, organisation, methods, starting_date, ending_date, tekst, logo, staatus, regStatus, cCat, credits, courseID ) if creating_new_course: if do_groupfolder: course_obj.add_folder('CourseFolder') else: if do_groupfolder and not course_obj.has_group_folder(): course_obj.add_folder('CourseFolder') # elif not do_groupfolder and course_obj.has_group_folder(): # course_obj._delObject('gf') if creating_new_course: self.change_course(REQUEST, course_id) REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+"/courses/"+course_id+"/manage_participants?pnimi=") else: REQUEST.RESPONSE.redirect(course_obj.absolute_url()+'/gf/course_info') #security.declareProtected(perm_edit, 'get_courses') security.declarePublic('get_courses') # No additional comments. def get_courses(self, REQUEST=None, **kw): """Return a list of Course objects in this manager.""" doSort = 0 doFilter = 0 try: doSort = int(REQUEST.get('sortc', 0)) except AttributeError: pass try: if int(REQUEST.filter): doFilter = int(REQUEST.filter) except AttributeError: pass if doSort == 1: return self.courses_zcatalog(meta_type='Course', sort_on='getCourseCategory') elif doSort == 99 and doFilter: return self.courses_zcatalog(meta_type='Course', getCourseCategory=doFilter, sort_on='getCourseCategory') elif doSort == 10: return self.courses_zcatalog(meta_type='Course', sort_on='getStatus') elif doSort == 20: return self.courses_zcatalog(meta_type='Course', sort_on='get_n_users') elif doSort == 30: return self.courses_zcatalog(meta_type='Course', sort_on='lastModify') elif doSort == 40: return self.courses_zcatalog(meta_type='Course', sort_on='lastActive') elif doSort == 50: return self.courses_zcatalog(meta_type='Course', sort_on='get_n_notes') elif doSort == 60: return self.courses_zcatalog(meta_type='Course', sort_on='get_n_artefacts') elif doFilter: return self.courses_zcatalog(meta_type='Course', getCourseCategory=doFilter, sort_on='getCourseCategory') else: return self.courses_zcatalog(meta_type='Course', sort_on='get_name', **kw) security.declareProtected(perm_edit, 'get_course_by_uniqid') def get_course_by_uniqid(self, uniqid): """ get course by uniq id """ result = self.courses_zcatalog(meta_type='Course', getUniqId=uniqid) if result: return result[0] return result security.declareProtected(perm_edit, 'get_user_ids_on_course') def get_user_ids_on_course(self, course_id): """Return UserInfo ids (list) on a given course.""" return self.get_child(course_id).get_all_users_id() #XXX: FIX: security check #security.declareProtected(perm_edit, 'get_users_not_on_the_course') security.declarePublic('get_users_not_on_the_course') def get_users_not_on_the_course(self, course_id, jarjestus="", omadus="", alates="", kuni=""): """Get all users who are not on the given course. Return list of UserInfo objects.""" try: course_obj = self.get_child(course_id) except AttributeError: raise 'FLE Error', 'Errorneous course id.' attendees = course_obj.get_all_users() if jarjestus=="": all_users = self.fle_users.get_users() if jarjestus=="kasutajanimi": all_users = self.fle_users.get_users_sorted_by_uname() non_att = [] faaeg = time.time() for user in all_users: if user not in attendees: lisada=1 if omadus!="": if alates != "": if user.kysi_omadus(omadus)kuni and (user.kysi_omadus(omadus)[:len(kuni)]!=kuni): lisada=0 if lisada: non_att.append(user) feaeg = time.time() return non_att security.declareProtected(perm_manage, 'courses_form_handler') # index_html form handler def courses_form_handler( self, REQUEST, delete='', # form submit button course_export='', course_ids=None, ): """Form handler for courses index page.""" import types if int(self.kas_opetaja(REQUEST))!=1: if not self.fle_root().fle_users.is_power_user(REQUEST.AUTHENTICATED_USER): return "Access denied" if not course_ids: return self.message_dialog_error( self, REQUEST, title='No course selected', message='Please select a course from the course list.', action='index_html') if delete: if type(course_ids) is types.StringType: course_ids=(course_ids,) return self.message_dialog2( self, REQUEST, title = 'Confirmation', message = translate(self, 'Are you sure you want to delete the following courses:', target=self.giveLanguage(REQUEST)) + ' ' + \ ', '.join([getattr(self, ci).get_name() for ci in course_ids]), handler = 'delete_courses_form_handler', extra_value_name = 'course_ids', extra_values = course_ids, option1_value = 'Cancel', option1_name = 'cancel', option2_value = 'Ok', option2_name = 'delete') #REQUEST.RESPONSE.redirect('index_html') elif course_export: if type(course_ids) is types.StringType: course_ids=(course_ids,) message = self.do_courses_export(course_ids) message = translate(self,'Exported course(s) are save to following location:',target=self.giveLanguage(REQUEST))+message return self.index_html(message=message) else: # This code should never be reached. raise 'FLE Error', 'Unknown button' security.declarePrivate('do_courses_export') # index_html form handler def do_courses_export(self,course_ids): message = "" for c_id in course_ids: course = self.get_child(c_id) message += '
' + course.iva_ims_export(teacherExporting=0) get_transaction().commit() return message # FIXME: input_checks security.declareProtected(perm_manage, 'delete_courses_form_handler') def delete_courses_form_handler( self, REQUEST, course_ids, delete='', cancel='', ): """Form handler that is called from message_dialog2.""" if delete: for course_id in course_ids: for wt in [user.get_webtop() for user in self.get_child(course_id).get_all_users()]: wt.recursive_delete_group_folder_proxy(course_id) [self.get_child(course_id).remove_person(user.get_uname()) for user in self.get_child(course_id).get_all_users()] self._delObject(course_id) elif cancel: pass else: # This code should never be reached. raise 'FLE Error', 'Unknown button' REQUEST.RESPONSE.redirect('index_html') security.declarePublic('has_courses') def has_courses(self): """Return boolean describing whether there is an existing course on the system.""" return not not self.get_children('Course') def get_course_id_from_req(self, req): """Extract a course id from REQUEST. This is needed by the CourseManager.course_selection dtml method.""" path = req.PATH_TRANSLATED splitter = '/' if splitter not in path: splitter = '\\' i = string.find(path, "courses") ri = string.rfind(path, "courses") if (i == -1) or (ri == -1): return None if (ri != i): # There is more than one 'courses' word in path. # We'll have to use the reverse one. i = ri plst = filter(lambda x:x, string.split(path[i:], splitter)) try: return plst[1] except IndexError: return None def get_formatted_current_date(self, REQUEST): """Return date formatted depending on user's language.""" return time.strftime(translate(self,'short_date_format',default="%Y-%m-%d",target=self.giveLanguage(REQUEST)), time.localtime()) def get_printable_starting_date(self, REQUEST): """ return current time, no starting time for coursemanager """ return self.get_formatted_current_date(REQUEST) def get_printable_ending_date(self, REQUEST): """ return current time, no ending time fot coursemanaget. this is here for course adding page """ return self.get_formatted_current_date(REQUEST) # security.declareProtected(perm_view, 'user_course_export') security.declarePublic('user_course_export') def user_course_export(self,REQUEST): """ user exports its course for viewing offline """ from ImportExportIMS import Kirjutus from ImportExportIMS import kirjutaYldM import tempfile, os uname = REQUEST.AUTHENTICATED_USER.getUserName() knr=self.fle_root().jooksva_kursuse_nr(self, REQUEST) # knr=self.fle_root().jooksva_kursuse_nr(self, REQUEST) knr = self.get_course_id_from_req(REQUEST) kasutaja = self.fle_users.get_user_info(uname) kasutaja = ((kasutaja),) failinimi = tempfile.mktemp() kursus = self.get_child(knr) k = Kirjutus(self.fle_root(), kursus.get_id()) k.looKursuseFail() k.kirjutaWebtop(kursus.gf, tiitel='RAAMATURIIUL') k.kirjutavCal(kursus.syndmused, 'kursus','GROUP') k.kirjutaKasutajaWebtop(kasutaja) k.kirjutaKasutajaSyndmus(kasutaja) # k.kirjutaWiki(getattr(kursus,'ivawiki')) for sisegr in kursus.subgroups.objectValues('GroupFolder'): sisegr_kasutajad = kursus.kasutajad_sisegrupis(sisegr.get_name()) if uname not in sisegr_kasutajad: continue k.kirjutaWebtop(sisegr,'SISEGRUPP') try: k.kirjutavCal(sisegr.syndmused,sisegr.get_name(),'GROUP') except: pass k.kirjutaKasutajaWiki(kasutaja) k.exportPajad(failinimi, str(kursus.get_name()+"/")) k.pakiKursusFaili(failinimi,str(kursus.get_name())) file = open(failinimi, "rb") export_data=file.read() file.close() os.remove(failinimi) REQUEST.RESPONSE.setHeader('content-type','application/zip') REQUEST.RESPONSE.setHeader('Content-disposition','attachment; filename=iva_arhiiv.zip') return export_data # XXX: Wikis are imported through that method. # XXX: and security is gone! security.declareProtected(perm_manage, 'import_form_handler') def import_form_handler( self, REQUEST, file, course_import='', testsonly='', wikionly='', cancel='', wiki_koht='', dry_run='', ): """Form handler for course importing.""" uname = REQUEST.AUTHENTICATED_USER.getUserName() from StringIO import StringIO out = StringIO() if testsonly: raise 'IVA Error:', 'Wrong place.' if wikionly: raise 'IVA Error:', 'Wrong place.' if course_import: from ImportExportIMS import Importer from ImportExport import Exporter import tempfile, os filename = tempfile.mktemp() f = open(filename,"w+b") f.write(file.read()) f.close() import_data=None imported = Importer(uname,self.fle_root(), out=out) imported.do_import_answers = 1 imported.loadZip(filename) element = imported.loadFile('imsmanifest.xml') imported.processFile(self,element) if dry_run: print >> out, "Dry run selected, transation aborted." get_transaction().abort() kala = "Import Course
imported" os.remove(filename) return self.defaultRender(page=re.sub('\n', '
', out.getvalue()), userLocation='Management') return security.declareProtected(perm_manage,'import_form_handler2') def import_form_handler2(self,REQUEST,zip='',importB=''): """ imports from zip, located at zope instance's import folder """ if not importB: return "x" if not zip: return "y" uname = str(REQUEST.AUTHENTICATED_USER) if importB: from ImportExportIMS import Importer from ImportExport import Exporter import os, time from StringIO import StringIO out = StringIO() insthome = Globals.INSTANCE_HOME oaeg_alg = time.time() for names in zip: zip_alg = time.time() try: path = os.path.join(insthome,'import') filename = os.path.join(path,names) except OSError: return "z" print filename imported = Importer(uname,self.fle_root(), out=out) imported.loadZip(filename) element = imported.loadFile('imsmanifest.xml') imported.processFile(self,element) zip_lopp = time.time() print "Zip:",zip_lopp-zip_alg get_transaction().commit() oaeg_lopp = time.time() print "Overall:", oaeg_lopp-oaeg_alg return self.index_html(message="File(s) successfully imported.") # return REQUEST.RESPONSE.redirect(self.fle_root().absolute_url()+'/courses/') def coursesOpenToRegister(self, knimi): """ Kursuste loetelu, kus kasutaja veel pole """ cm=self.get_courses(getRegStatus=['1','2']) loetelu=[] for c in cm: leidub=0 rm=c.getObject().get_local_roles() for r in rm: if str(knimi)==r[0]: leidub=1 if c.getObject().kasOotaja(knimi): leidub=1 if not leidub:# and ((c.getStatus=='1') or (c.getObject().getStatus()=='4')): loetelu.append(c) return loetelu #security.declareProtected(, 'kursusteleRegistreerimiseLeht') def kursusteleRegistreerimiseLeht(self, REQUEST,kursus=()): "Kasutajate lisamine ootele" import types if type(kursus)==types.StringType: kursus=(kursus,) for x in kursus: getattr(self, x).lisaOotaja(REQUEST, str(REQUEST.AUTHENTICATED_USER)) return REQUEST.RESPONSE.redirect('organizer_openCourses') def getStatuses(self): """ return course statuses """ return range(3) def getPrintableStatus(self, nr): """ return printable course status """ statuses = ['Preparation', 'Active', 'Finished'] if int(nr)>2: return 'Invalid status' return statuses[int(nr)] def getRegStatuses(self): """ return course registration status """ return range(3) def getPrintableRegStatus(self, nr): """ return printable registration status """ statuses = ['by teacher', 'with teacher\'s permission', 'automatically'] return statuses[int(nr)] security.declareProtected(perm_view, 'get_unames_on_my_courses') def get_unames_on_my_courses(self, REQUEST): """Return a list of unames (users that are on some course than the caller.""" uname = str(REQUEST.AUTHENTICATED_USER) uname_list = [] for course in self.get_courses(): unames_in_course = course.get_all_users_id() if uname in unames_in_course: uname_list += unames_in_course retval = [] for uname in uname_list: if uname not in retval: retval.append(uname) return retval security.declareProtected(perm_manage, 'giveCategories') def giveCategories(self): #XXX: not needed!? return self.cCategories.keys() # security.declareProtected(perm_view,'getAllCategories') def getAllCategories(self): return self.cCategories['groups'].keys() def getACat(self,id): try: return self.cCategories['relations'][str(id)] except KeyError: return None # security.declareProtected(perm_view, 'treePrinter') def treePrinter(self): """ tree printer """ result = [] init = self.getCatForCat() for x in init: tmp = [] tmp.append('') tmp.append(x) result.append(tmp) self.treeSlave(x,'-',result) return result # teachers are getting errors... # security.declareProtected(perm_view,'getNameForID') def getNameForID(self, id): try: int_id = int(id) except ValueError: int_id = 0 if id is not None and int_id != 0: try: return self.cCategories['groups'][int(id)]['Name'] except KeyError: return "deleted..." else: return "" def getParentForID(self, id): try: return self.cCategories['groups'][id]['Parent'] except KeyError: return '' security.declarePrivate('addcCategory') def addcCategory(self, newcat, undercat): from random import random id = int(round(random()*1000000000)) self.cCategories['groups'][id] = {'Name':newcat, 'Parent':undercat} self.cCategories._p_changed = 1 security.declarePrivate('renameCategory') def renameCategory(self, id, newname): self.cCategories['groups'][int(id)]['Name'] = newname self.cCategories._p_changed = 1 security.declarePrivate('removeCategory') def removeCategory(self, id): self.cCategories['groups'].pop(int(id)) self.cCategories._p_changed=1 security.declarePrivate('treeSlave') def treeSlave(self,cat, sep,result): for x in self.getCatForCat(cat): tmp = [] tmp.append(sep) tmp.append(x) result.append(tmp) self.treeSlave(x,sep+'-',result) return result def getCatForCat(self,parent=''): #pass cats = [] if parent == '': parent = 'None' else: parent = str(parent) for x in self.cCategories['groups'].keys(): if self.cCategories['groups'][x]['Parent'] == parent: cats.append(x) return cats security.declareProtected(perm_manage,'manageCategories_handler') def manageCategories_handler(self, REQUEST, saveB='', deleteB='', deletec='', newCat='', underCat='', renameB='', renaming='', newname=''): """ creates or deletes course category """ if saveB: if not underCat: underCat = 'None' if newCat: self.addcCategory(newCat, underCat) if deleteB: if type(deletec)==types.StringType: deletec=(deletec,) for dc in deletec: self.removeCategory(dc) if renameB and newname and renaming: self.renameCategory(renaming, newname) return REQUEST.RESPONSE.redirect(self.absolute_url()+'/manageCategories') self.cCategories = PersistentMapping() self.cCategories['groups'] = {} # self.cCategories['relations'] = {} self.cCategories._p_changed = 1 def isCourseReady(self,course=None): """ if all course fields are filled """ if not course: return 0 #if not int(course.getStatus()) or int(course.getStatus()==3): return 0 if not course.get_name() or not course.get_organisation() or not course.get_description() or not course.get_methods() or not course.get_start_date() or not course.get_end_date(): return 0 return 1 security.declareProtected(perm_manage,'ziplist') def ziplist(self): """ returns a list of importable zip-s """ import os insthome = Globals.INSTANCE_HOME try: impath = os.path.join(insthome,'import') except OSError: return "no import folder found at %s" % insthome files = [] for x in os.listdir(impath): if x[-4:].lower() == '.zip':files.append(x) return files def change_course(self, REQUEST, course_nr): """ change course """ if not course_nr: return user = self.fle_users.get_user_info(str(REQUEST.AUTHENTICATED_USER)) res = user.set_jooksev_kursus(course_nr, user.get_uname()) try: c = self.get_child(course_nr) except KeyError: return if not res: return wt = getattr(user, 'webtop', None) if wt is None: return cw = getattr(wt, 'c'+course_nr, None) folder = None if cw is None: #wt.lisa_kursuse_kaust(REQUEST, 'c'+course_nr) folder = wt.add_folder('c'+course_nr, 'c'+course_nr) folder.set_author(str(REQUEST.AUTHENTICATED_USER)) else: folder = cw user.check_portfolios(folder, c) self.updateStat(REQUEST, 'numTimesEntered', int(course_nr)) self.registerVisit(REQUEST, course_nr, 'Organizer') return REQUEST.RESPONSE.redirect(c.absolute_url()+'/course_index') Globals.InitializeClass(CourseManager) # EOF