Annotation of MPIWGWeb/MPIWGRoot.py, revision 1.1.2.2
1.1.2.1 dwinter 1: from Products.PageTemplates.PageTemplateFile import PageTemplateFile
2: from Products.PageTemplates.PageTemplate import PageTemplate
3: from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
4: from Products.ZSQLExtend.ZSQLExtend import ZSQLExtendFolder
5: from Products.ZCatalog.CatalogPathAwareness import CatalogAware
6: from OFS.Image import Image
7: from Globals import package_home
8: import urllib
9: import MPIWGStaff
10: import string
11: import re
12: import os
13: from types import *
14: import logging
15: import xmlhelper # Methoden zur Verwaltung der projekt xml
16: from OFS.SimpleItem import SimpleItem
17: from OFS.Folder import Folder
18: from Products.ZSQLMethods.SQL import SQLConnectionIDs
19: from AccessControl import ClassSecurityInfo
20: from bibliography import *
21: import time
22: import xml.dom.minidom
23: import sys
24: from Ft.Xml.XPath import Evaluate
25: from Ft.Xml.XPath.Context import Context
26: from Ft.Xml.Domlette import NonvalidatingReader,PrettyPrint, Print
27: from Ft.Xml import EMPTY_NAMESPACE
28: import copy
29: import updatePersonalWWW
30: import MPIWGStaff
31: from MPIWGHelper import *
32:
33: class MPIWGRoot(ZSQLExtendFolder):
34: """Stammordner fuer den Web-Server"""
35:
36: fieldLabels={'WEB_title':'WEB_Title','xdata_01':'Responsible Scientists','xdata_02':'Department',
37: 'xdata_03':'Historical Persons','xdata_04':'Time period',
38: 'xdata_05':'Sorting number','xdata_06':'Keywords','xdata_07':'Short title',
39: 'xdata_08':'Other involved scholars' ,'xdata_09':'Disciplines','xdata_10':'Themes',
40: 'xdata_11':'Object Digitallibrary','xdata_12':'Cooperation partners',
41: 'xdata_13':'Funding institutions','WEB_project_header':'WEB_project_header',
42: 'WEB_project_description':'WEB_project_description','WEB_related_pub':'WEB_related_pub'}
43:
44: folders=['MPIWGProject','Folder','ECHO_Navigation']
45: meta_type='MPIWGRoot'
46:
47: def transformProjectsToId(self):
48: """trnasformiere zu ID, Hilfsfunktion die die alten Templates analysiert und mit der neuen Liste
49: verantwortlicher Personen versieht"""
50: projects=self.getTree()
51: ret=""
52: for project in projects:
53: proj=project[3]
54: persons=proj.identifyNames(proj.getContent('xdata_01'))
55: if not hasattr(proj,'responsibleScientistsList'):
56: proj.responsibleScientistsList=[]
57:
58: for person in persons.items():
1.1.2.2 ! dwinter 59:
1.1.2.1 dwinter 60: if len(person[1]) >1: #nicht eindeutig
61: ret+="nicht eindeutig --- %s: %s\n"%(proj.getId(),person[0])
62:
63: elif len(person[1]) ==0: #kein eintrage
64: ret+="kein eintrag--- %s: %s\n"%(proj.getId(),person[0])
65: proj.responsibleScientistsList.append((person[0],""))
66: else:
67: proj.responsibleScientistsList.append((person[0],person[1][0].getObject().getKey()))
68:
69: return ret
70:
71: def harvestProjects(self):
72: """harvest"""
73: folder="/tmp"
74: try:
75: os.mkdir("/tmp/harvest_MPIWG")
76: except:
77: pass
78: founds=self.ZopeFind(self.aq_parent.projects,obj_metatypes=['MPIWGProject'],search_sub=1)
79: for found in founds:
80: txt=found[1].harvest_page()
81:
82: if txt and (txt != ""):
83: name=found[0].replace("/","_")
84: fh=file("/tmp/harvest_MPIWG/"+name,"w")
85: fh.write(txt)
86: fh.close()
87:
88: def decode(self,str):
89: """decoder"""
90: if not str:
91: return ""
92: if type(str) is StringType:
93: try:
94: return str.decode('utf-8')
95: except:
96: return str.decode('latin-1')
97: else:
98: return str
99:
100:
101: def getat(self,array,idx=0,default=None):
102: """return array element idx or default (but no exception)"""
103: if len(array) <= idx:
104: return default
105: else:
106: return array[idx]
107:
108:
109: def browserCheck(self):
110: """check the browsers request to find out the browser type"""
111: bt = {}
112: ua = self.REQUEST.get_header("HTTP_USER_AGENT")
113: bt['ua'] = ua
114: bt['isIE'] = False
115: bt['isN4'] = False
116: if string.find(ua, 'MSIE') > -1:
117: bt['isIE'] = True
118: else:
119: bt['isN4'] = (string.find(ua, 'Mozilla/4.') > -1)
120:
121: try:
122: nav = ua[string.find(ua, '('):]
123: ie = string.split(nav, "; ")[1]
124: if string.find(ie, "MSIE") > -1:
125: bt['versIE'] = string.split(ie, " ")[1]
126: except: pass
127:
128: bt['isMac'] = string.find(ua, 'Macintosh') > -1
129: bt['isWin'] = string.find(ua, 'Windows') > -1
130: bt['isIEWin'] = bt['isIE'] and bt['isWin']
131: bt['isIEMac'] = bt['isIE'] and bt['isMac']
132: bt['staticHTML'] = False
133:
134: return bt
135:
136:
137: def versionHeaderEN(self):
138: """version header text"""
139:
140: date= self.REQUEST.get('date',None)
141: if date:
142: txt="""<h2>This pages shows the project which existed at %s</h2>"""%str(date)
143: return txt
144: return ""
145:
146: def versionHeaderDE(self):
147: """version header text"""
148: date= self.REQUEST.get('date',None)
149: if date:
150: txt="""<h2>Auf dieser Seite finden Sie die Projekte mit Stand vom %s</h2>"""%str(date)
151: return ""
152:
153:
154: def createOrUpdateId_raw(self):
155: """create sequence to create ids for bibliography"""
156: debug=None
157: #suche groesste existierende id
158: founds=self.ZSQLQuery("select id from bibliography")
159:
160: if founds:
161: ids=[int(x.id[1:]) for x in founds]
162: maximum=max(ids)
163:
164: id_raw=self.ZSQLQuery("select nextval('id_raw')",debug=debug)
165:
166: if id_raw:
167: self.ZSQLQuery("drop sequence id_raw",debug=debug)
168:
169: self.ZSQLQuery("create sequence id_raw start %i"%(maximum+1),debug=debug)
170:
171:
172: def queryLink(self,link):
173: """append querystring to the link"""
174: return "%s?%s"%(link,self.REQUEST.get('QUERY_STRING',''))
175:
176: def getKategory(self,url):
177: """kategorie"""
178: splitted=url.split("/")
179: return splitted[4]
180:
181: def generateUrlProject(self,url,project=None):
182: """erzeuge aus absoluter url, relative des Projektes"""
183: if project:
184: splitted=url.split("/")
185: length=len(splitted)
186: short=splitted[length-2:length]
187:
188: base=self.REQUEST['URL3']+"/"+"/".join(short)
189:
190: else:
191: findPart=url.find("/projects/")
192: base=self.REQUEST['URL1']+"/"+url[findPart:]
193:
194:
195: return base
196:
197: def isNewCapital(self,text=None,reset=None):
198: if reset:
199: self.REQUEST['capital']="A"
200: return True
201: else:
202: if len(text)>0 and not (text[0]==self.REQUEST['capital']):
203: self.REQUEST['capital']=text[0]
204: return True
205: else:
206: return False
207:
208: def subNavStatic(self,obj):
209: """subnav" von self"""
210: def sortWeight(x,y):
211: x1=int(getattr(x[1],'weight','0'))
212: y1=int(getattr(y[1],'weight','0'))
213: return cmp(x1,y1)
214:
215: subs=self.ZopeFind(obj,obj_metatypes=['MPIWGTemplate','MPIWGLink'])
216: subret=[]
217:
218: for x in subs:
219: if not(x[1].title==""):
220: subret.append(x)
221: subret.sort(sortWeight)
222: return subret
223:
224: def subNav(self,obj):
225: """return subnav elemente"""
226: def sortWeight(x,y):
227: x1=int(getattr(x[1],'weight','0'))
228: y1=int(getattr(y[1],'weight','0'))
229: return cmp(x1,y1)
230: #if obj.meta_type in ['MPIWGTemplate','MPIWGLink']:
231: # id=obj.aq_parent.getId()
232: #else:
233:
234: #id=obj.getId()
235:
236:
237: #suche die zweite ebene
238:
239: if not obj.aq_parent.getId() in ['de','en']:
240: obj=obj.aq_parent
241:
242: while not self.ZopeFind(self,obj_ids=[obj.getId()]):
243: obj=obj.aq_parent
244:
245:
246: if hasattr(self,obj.getId()):
247:
248: subs=self.ZopeFind(getattr(self,obj.getId()),obj_metatypes=['MPIWGTemplate','MPIWGLink'])
249: subret=[]
250:
251: for x in subs:
252: if not(x[1].title==""):
253: subret.append(x)
254: subret.sort(sortWeight)
255: return subret
256: else:
257: return None
258:
259: def isActive(self,name):
260: """teste ob subnavigation aktiv"""
261: for part in self.REQUEST['URL'].split("/"):
262: if part==name:
263: return True
264: return False
265:
266: def getSection(self):
267: """returns the current section name"""
268: root = self.absolute_url()
269: url = self.REQUEST['URL']
270: if not url:
271: return None
272: path = string.replace(url, root, '')
273: paths = path.split('/')
274: if len(paths) > 0:
275: sec = paths[1]
276: if sec.find('.') < 0:
277: return sec
278: else:
279: return None
280: return None
281:
282: def getSectionStyle(self, name, style=""):
283: """returns a string with the given style + '-sel' if the current section == name"""
284: if self.getSection() == name:
285: return style + '-sel'
286: else:
287: return style
288:
289: def MPIWGrootURL(self):
290: """returns the URL to the root"""
291: return self.absolute_url()
292:
293: def upDateSQL(self,fileName):
294: """updates SQL databases using fm.jar"""
295: fmJarPath=os.path.join(package_home(globals()), 'updateSQL/fm.jar')
296: xmlPath=os.path.join(package_home(globals()), "updateSQL/%s"%fileName)
297: logger("MPIWG Web",logging.INFO,"java -classpath %s -Djava.awt.headless=true Convert %s"%(fmJarPath,xmlPath))
298: ret=os.popen("java -classpath %s -Djava.awt.headless=true Convert %s"%(fmJarPath,xmlPath),"r").read()
299: logger("MPIWG Web",logging.INFO,"result convert: %s"%ret)
300: return 1
301:
302: def patchProjects(self,RESPONSE):
303: """patch"""
304: projects=self.ZopeFind(self.projects,obj_metatypes=['MPIWGProject'])
305: for project in projects:
306: tmp=project[1].WEB_project_description[0].replace("/CD/projects/","")[0:]
307: setattr(project[1],'WEB_project_description',[tmp[0:]])
308: RESPONSE.write("<p>%s</p>\n"%project[0])
309:
310: def replaceNotEmpty(self,format,field):
311: """replace not empty"""
312: if field and (not field.lstrip()==''):
313: return format%field
314: else:
315: return ""
316:
317:
318: def isActiveMember(self,key):
319: """tested ob Mitarbeiter key ist aktiv"""
320: ret=self.getat(self.ZSQLInlineSearch(_table='personal_www',
321: _op_key='eq',key=key,
322: _op_publish_the_data='eq',
323: publish_the_data='yes'))
324:
325: logging.info("ACTIVE_MEMBER %s"%ret)
326: if ret:
327: return True
328: else:
329: return False
330:
331: def isActual(self,project):
332: """checke if project is actual"""
333: actualTime=time.localtime()
334:
335: if hasattr(project,'getObject'): #obj ist aus einer catalogTrefferList
336: obj=project.getObject()
337: else:
338: obj=project
339:
340: if getattr(obj,'archiveTime',actualTime)< actualTime:
341: return False
342: else:
343: return True
344:
345: def redirectIndex_html(self,request):
346: #return request['URL1']+'/index_html'
347:
348: return urllib.urlopen(request['URL1']+'/index_html').read()
349:
350:
351: def formatBibliography(self,here,found):
352: """format"""
353: return formatBibliography(here,found)
354:
355: def getValue(self,fieldStr):
356: """Inhalt des Feldes"""
357:
358: if type(fieldStr)==StringType:
359: field=fieldStr
360: else:
361: field=fieldStr[0]
362: try:
363: if field[len(field)-1]==";":
364: field=field[0:len(field)-1]
365: except:
366:
367: """nothing"""
368: field=re.sub(r';([^\s])','; \g<1>',field)
369: return field.encode('utf-8')
370:
371:
372:
373: def sortedNames(self,list):
374: """sort names"""
375:
376: def sortLastName(x_c,y_c):
377: try:
378: x=urllib.unquote(x_c).encode('utf-8','ignore')
379: except:
380: x=urllib.unquote(x_c)
381:
382: try:
383: y=urllib.unquote(y_c).encode('utf-8','ignore')
384: except:
385: x=urllib.unquote(y_c)
386:
387:
388:
389: try:
390: last_x=x.split()[len(x.split())-1]
391: last_y=y.split()[len(y.split())-1]
392:
393: except:
394:
395: last_x=""
396: last_y=""
397:
398:
399:
400: if last_x<last_y:
401: return 1
402: elif last_x>last_y:
403: return -1
404: else:
405: return 0
406:
407: list.sort(sortLastName)
408: list.reverse()
409:
410: return list
411:
412: def __init__(self, id, title):
413: """init"""
414: self.id=id
415: self.title=title
416:
417: def removeStopWords(self,xo):
418: """remove stop words from xo"""
419: if not hasattr(self,'_v_stopWords'):
420: self._v_stopWords=self.stopwords_en.data.split("\n")
421:
422: x=str(xo)
423:
424: strx=x.split(" ")
425:
426: for tmp in strx:
427:
428: if tmp.lower() in self._v_stopWords:
429: del strx[strx.index(tmp)]
430:
431: return " ".join(strx)
432:
433: def urlQuote(self,str):
434: """quote"""
435: return urllib.quote(str)
436:
437: def urlUnQuote(self,str):
438: """quote"""
439: return urllib.unquote(str)
440:
441:
442:
443: def getProjectsByFieldContent(self,fieldName,fieldContentsEntry, date=None):
444: """gib alle Projekte aus mit Value von field mit fieldName enthaelt ein Element der Liste fieldContents"""
445: def sort(x,y):
446: return cmp(x.WEB_title[0],y.WEB_title[0])
447:
448: if type(fieldContentsEntry) is StringType:
449: fieldContentsTmp=[fieldContentsEntry]
450: else:
451: fieldContentsTmp=fieldContentsEntry
452:
453: fieldContents=[]
454: for x in fieldContentsTmp:
455: fieldContents.append(" AND ".join(x.split()))
456: projects=self.ProjectCatalog({fieldName:string.join(fieldContents,' AND')})
457: #print projects
458: #ret=[x for x in projects]
459: ret=[]
460: for x in projects:
461: obj=x.getObject()
462: obj=obj.getActualVersion(date)
463: if obj and (not getattr(obj,'invisible',None)):
464: #if not (x in ret):
465: ret.append(x)
466:
467: ret.sort(sort)
468: return ret
469:
470: def changeMPIWGRootForm(self):
471: """edit"""
472: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','changeMPIWGRootForm')).__of__(self)
473: return pt()
474:
475: def changeMPIWGRoot(self,title,disciplineList,themesList,connection_id,RESPONSE=None):
476: """change"""
477: self.title=title
478: self.connection_id=connection_id
479: self.disciplineList=disciplineList
480: self.themesList=themesList
481:
482: if RESPONSE is not None:
483: RESPONSE.redirect('manage_main')
484:
485:
486:
487: def getContexts(self,childs=None,parents=None,depth=None,date=None,onlyActive=True):
488: """childs alle childs, alle parents"""
489: ret=[]
490:
491: if parents:
492: splitted=parents.split(".")
493: parentId=string.join(splitted[0:len(splitted)-1],".")
494:
495: for project in self.getProjectFields('xdata_05',sort='int',date=date):
496: if project[1]==parentId:
497: ret.append(project)
498:
499: if childs:
500: for project in self.getProjectFields('xdata_05',sort='int',date=date):
501: searchStr=childs+"(\..*)"
502:
503: if (onlyActive and project[0].isActiveProject()) or (not onlyActive):
504: if re.match(searchStr,project[1]):
505:
506: if depth:
507:
508: if int(depth)>=len(project[1].split("."))-len(childs.split(".")):
509:
510: ret.append(project)
511: else:
512: ret.append(project)
513: return ret
514:
515: def getProjectFields(self,fieldName,date=None,folder=None,sort=None):
516: """getListofFieldNames"""
517: ret=[]
518:
519: objects=self.ZopeFind(self.projects,obj_metatypes=['MPIWGProject'],search_sub=0)
520:
521:
522: for object in objects:
523: obj=object[1]
524: obj=obj.getActualVersion(date)
525: if obj and (not getattr(obj,'invisible',None)):
526: if fieldName=="WEB_title_or_short":
527:
528: if len(obj.getContent('xdata_07'))<3: # hack weil z.Z. manchmal noch ein Trennzeichen ; oder , im Feld statt leer
529: fieldNameTmp="WEB_title"
530: else:
531: fieldNameTmp="xdata_07"
532: else:
533: fieldNameTmp=fieldName
534:
535: ret.append((obj,obj.getContent(fieldNameTmp)))
536:
537:
538: if sort=="int":
539: ret.sort(sortI)
540: elif sort=="stopWords":
541:
542: ret.sort(sortStopWords(self))
543:
544: else:
545: ret.sort(sortF)
546:
547: return ret
548:
549: def showNewProjects(self):
550: projects=[]
551: for objs in self.getProjectFields('WEB_title_or_short'): # Get all Projets
552: if objs[0].xdata_05 and (objs[0].xdata_05[0] == ""):
553:
554: projects.append(objs)
555:
556: return projects
557:
558:
559: manage_options = Folder.manage_options+(
560: {'label':'Update personal homepages','action':'updatePersonalwww_html'},
561: {'label':'Reindex catalogs','action':'reindexCatalogs'},
562: {'label':'Main config','action':'changeMPIWGRootForm'},
563: {'label':'add e-mails','action':'showNewDBEntries'},
564: {'label':'update the institutsbibliography','action':'updateInstitutsbiliography'},
565: #{'label':'Edit Historical Persons','action':'editHistoricalPersonsForm'},
566: #{'label':'Store Historical Persons','action':'storeHistoricalPersons'},
567: )
568:
569:
570: def updatePublicationDB(self,personId=None):
571: """updates the publication db, i.e. copy year and type into the main table"""
572:
573: if personId:
574: founds = self.ZSQLInlineSearch(_table="publications",key_main=personId)
575: else:
576: founds = self.ZSQLInlineSearch(_table="publications")
577:
578: for found in founds:
579:
580: if found.id_institutsbibliographie and (not found.id_institutsbibliographie =="") and (not found.id_institutsbibliographie =="0"):
581:
582: entries = self.ZSQLInlineSearch(_table="institutsbiblio",id=found.id_institutsbibliographie)
583: for entry in entries:
584: self.ZSQLChange(_table='publications',_identify='oid=%s' % found.oid,year=entry.year,referencetype=entry.reference_type)
585:
586: if found.id_gen_bib and (not found.id_gen_bib ==""):
587: entries = self.ZSQLInlineSearch(_table="bibliography",id=found.id_gen_bib)
588: for entry in entries:
589: self.ZSQLChange(_table='publications',_identify='oid=%s' % found.oid,year=entry.year,referencetype=entry.reference_type)
590:
591: return True
592:
593: def showNewDBEntries(self):
594: """zeige neue Eintraege in der Datenbank ohne e-mail adressen bzw. fuer die noch kein Object angelegt wurde"""
595:
596: qstr="select * from personal_www where web_object_created='no' and not key=''"
597: res=self.ZSQLQuery(qstr)
598:
599: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','showNewDBEntries.zpt')).__of__(self)
600: return pt(newEntries=res)
601:
602: def createNewStaffObjects(self,RESPONSE):
603: """create new staff object"""
604:
605: memberFolder=getattr(self,'members')
606: args=self.REQUEST.form
607: arg_k=args.keys()
608: arg_k.remove("submit")
609: ret=""
610: for key in arg_k:
611: k=self.urlUnQuote(key)
612:
613: qstr="select * from personal_www where key=%s"%self.ZSQLQuote(k)
614: res=self.ZSQLQuery(qstr)[0]
615: if args[key]!="": #email-adresse wurde eingetragen
616: #create the object
617: e_mail=args[key]
618: try:
619: newObj=MPIWGStaff.MPIWGStaff(e_mail,res.last_name,res.first_name,k)
620: memberFolder._setObject(e_mail,newObj)
621: obj=getattr(memberFolder,e_mail)
622: obj.reindex_object()
623: ret+="Created %s \n"%e_mail
624: created=True
625: except:
626: msg="Cannot create new user %s (%s %s)"%(e_mail,sys.exc_info()[0],sys.exc_info()[1])
627: logging.error(msg)
628: ret+=msg+"\n"
629: created=False
630:
631: if created:
632: qstr="update personal_www set web_object_created='yes',e_mail='%s@mpiwg-berlin.mpg.de' where key=%s"%(e_mail,self.ZSQLQuote(k))
633: self.ZSQLQuery(qstr)
634:
635: return ret
636:
637:
638: def generateNewPersonEntry(self,data):
639: """generate a new person entry for data, neue personen werden zunaechst nur in der datenbank angelegt """
640:
641: #memberFolder=getattr(self,'members')
642: #create the object
643:
644: # try:
645: # newObj=MPIWGStaff.MPIWGStaff(urllib.quote(data['key']),data['last_name'].encode('utf-8'),data['first_name'].encode('utf-8'))
646: # memberFolder._setObject(urllib.quote(data['key']),newObj)
647: # except:
648: # return False, "Cannot create new user %s (%s %s)"%(data['key'],sys.exc_info()[0],sys.exc_info()[1])
649: #
650:
651: #create the new entry in the database
652:
653:
654: result,msg=MPIWGStaff.createNewDBEntry(self,data['publish_the_data'],data['key'],data['last_name'],
655: data['first_name'],data['title'],data['status'],"",
656: "",data['date_from'],data['date_to'],
657: data['department'],data['home_inst'],data['funded_by'],
658: data['e_mail2'],data['current_work'],"yes",data['date_stay_at_mpiwg'],data['group'],"no",data['current_work'])
659:
660: return result,msg
661:
662: def updatePersonEntry(self,data,ignoreEntries=[]):
663: """update an person entry from data. but ignore all fields in ignore Entries"""
664:
665: ignoreEntries.append('current_work') # TODO:updatecurrent work
666:
667: if data['date_to']=="": # wenn date_to leer
668: data['date_to']="date_none"
669:
670: if data['date_from']=="": # wenn date_fromleer
671: data['date_from']="date_none"
672: msg=""
673:
674:
675: #eintragen
676:
677: columns=data.keys()
678: for x in ignoreEntries:
679: logging.info("ign rem: %s"%x)
680: try: #falls in ignore entries felder sind, die nicht in columns sind, fange den fehler ab
681: columns.remove(x)
682: except:
683: pass
684:
685:
686: insert=[]
687: for key in columns:
688: if data[key]=="date_none": # date_none eintrag wird zu null uebersetzt
689: insert.append('%s=null'%key)
690: else:
691: insert.append(""" "%s"=%s"""%(key,self.ZSQLQuote(data[key])))
692:
693: insertStr=",".join(insert)
694: queryStr="update personal_www SET %s where key='%s'"%(insertStr,data['key'])
695: self.ZSQLQuery("SET DATESTYLE TO 'German'")
696: self.ZSQLQuery(queryStr)
697:
698: #currentwork
699: #if not (txt==""):
700: # queryStr="INSERT INTO current_work (id_main,current,publish) VALUES ('%s','%s','%s')"%(id,txt,txt_p)
701: #
702: # self.ZSQLQuery(queryStr)
703:
704: return True,msg
705:
706:
707: def updatePersonalwww_doIt(self):
708: """do the update"""
709: args=self.REQUEST.form
710: resultSet=self.REQUEST.SESSION['personal_www']['resultSet']
711: news=self.REQUEST.SESSION['personal_www']['news']
712: conflicts=self.REQUEST.SESSION['personal_www']['conflicts']
713: ret="<html><body>"
714: # generate the new entry
715:
716: if news and (len(news)>0):
717: ret+="<h2>Hinzugefügt</h2>"
718: ret+="<p>Neueinträge erscheinen erst auf der Homepage, wenn ihnen eine e-mail Adresse zugeordnet wurde.</p>"
719: ret+="<ul>"
720: for new in news:
721:
722: if args.has_key(self.urlQuote(new.encode('utf-8'))): # entry was selected
723: result,msg=self.generateNewPersonEntry(resultSet[new])
724: if not result:
725: logging.error("Error (generateNewPersonEntry) %s"%msg)
726: ret+="<li>ERROR: %s %s"%(new.encode('utf-8'),msg)
727: else:
728: ret+="<li>OK: %s"%(new.encode('utf-8'))
729: if news and (len(news)>0):
730: ret+="<p>Neueinträge erscheinen erst auf der Homepage, wenn ihnen eine e-mail Adresse zugeordnet wurde.</p>"
731: ret+="</ul>"
732:
733: # update
734:
735: if len(conflicts.keys())>0:
736: ret+="<h2>Änderung des Benutzers übernehmen</h2>"
737: ret+="<p>Wenn nötig in Filemaker-db ändern:</p>"
738:
739: # konflicte
740: for conflict in conflicts.keys():
741: ignoreEntries=[]
742: displayIgnored=[]
743: for cf in conflicts[conflict]:
744: if args[conflict.encode('utf-8')+'_'+cf[0]]=="stored": #use the stored one
745: ignoreEntries.append(cf[0]) #so ignore field cf[0]
746: displayIgnored.append(cf)
747: if len(displayIgnored)>0:
748: ret+="<h3>%s</h3>"%conflict.encode('utf-8')
749:
750: ret+="<table border='1'>"
751: for iE in displayIgnored:
752: ret+="<tr><td>%s</td><td>%s</td><td>%s</td>"%(iE[0].encode('utf-8'),iE[1].encode('utf-8'),iE[2].encode('utf-8'))
753: ret+="</tabel>"
754:
755: self.updatePersonEntry(resultSet[conflict],ignoreEntries=ignoreEntries)
756:
757: # rest
758: cl=list(conflicts.keys())
759:
760: for key in resultSet.keys():
761: if key not in cl:
762: self.updatePersonEntry(resultSet[key])
763: return ret+"</body></html>"
764:
765:
766: def updateInstitutsbiliography(self):
767: """update the Institutsbibliogrpahy"""
768: self.upDateSQL('personalwww.xml')
769: return "<html><body>DONE</body></html>"
770:
771:
772: def updatePersonalwww_html(self):
773: """update form for the homepages web form"""
774: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','updatePersonalwww.zpt')).__of__(self)
775: return pt()
776:
777:
778: def updatePersonalwww(self,uploadfile):
779: """update personalwww
780: @param uploadfile: file handle auf das file
781: """
782: dsn=self.getConnectionObj().connection_string
783: #dsn="dbname=personalwww"
784: resultSet=updatePersonalWWW.importFMPXML(uploadfile)
785: news,conflicts=updatePersonalWWW.checkImport(dsn, resultSet)
786:
787: self.REQUEST.SESSION['personal_www']={}
788: self.REQUEST.SESSION['personal_www']['resultSet']=resultSet
789: self.REQUEST.SESSION['personal_www']['news']=news
790: self.REQUEST.SESSION['personal_www']['conflicts']=conflicts
791:
792: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','updatePersonalwww_check.zpt')).__of__(self)
793: return pt()
794:
795:
796:
797: def reindexCatalogs(self,RESPONSE=None):
798: """reindex members and project catalog"""
799:
800:
801: try:
802:
803: self.ProjectCatalog.manage_catalogReindex(self.REQUEST,RESPONSE,self.REQUEST['URL1'])
804: except:
805: logger("MPIWG Root (updatehomepage)",logging.WARNING," %s %s"%sys.exc_info()[:2])
806:
807:
808:
809:
810:
811: if RESPONSE:
812: RESPONSE.redirect('manage_main')
813:
814:
815:
816:
817: def getAllMembers(self):
818: #ret=[]
819:
820: def sorter(x,y):
821: return cmp(x[0],y[0])
822:
823: results=self.MembersCatalog({'isPublished':True})
824:
825: ret=[(", ".join([proj.lastName, proj.firstName]).decode('utf-8'),proj.getKey) for proj in results]
826:
827: ret.sort(sorter)
828: return ret
829:
830:
831: def printAllMembers(self):
832: """print"""
833: members=self.getAllMembers()
834: ret=""
835: for x in members:
836: ret+="<p>%s</p>"%x
837: return ret
838:
839:
840: def makeList(self,entry):
841: """makes a list out of one entry or repeat a list"""
842: if type(entry) is StringType:
843: return [entry]
844: else:
845: return entry
846:
847:
848: def getTree(self,dep=None,date=None,onlyActive=0,onlyArchived=0):
849: """generate Tree from project list
850: als Liste, jeder Eintrag ist ein Tupel ,(Tiefe, ProjektNummer,ProjektObject
851: onlyActive = 0 : alle Projekte
852: onlyActive = 1 : nur active Projekte
853: onlyActive = 2: nur inactive Projekte
854:
855: onlyArchived=0: alle Projekte
856: onlyArchived= 1 : nur aktuelle Projekte
857: onlyArchived = 2: nur archivierte Projekte
858: """
859:
860: returnListTmp=[]
861: returnList=[]
862:
863: for project in self.getProjectFields('xdata_05',sort="int",date=date): # get Projects sorted by xdata_05
864:
865: for idNr in project[1].split(";"): # more than one number
866: if not idNr=="":
867: splittedId=idNr.split(".")
868: depth=len(splittedId)
869: nr=idNr
870: #title=project[0].WEB_title
871: title=[project[0].getContent('WEB_title')]
872: #print title
873:
874: if idNr[0]=="x": # kompatibilitaet mit alter Konvention, x vor der Nummer macht project inactive
875: project[0].setActiveFlag(False)
876:
877: if (not dep) or (idNr[0]==dep): #falls dep gesetzt ist nur dieses hinzufuegen.
878:
879: if (onlyActive==0):
880: returnListTmp.append((depth,nr,title,project[0]))
881: elif (onlyActive==1) and project[0].isActiveProject(): #nur active projekte
882: returnListTmp.append((depth,nr,title,project[0]))
883: elif (onlyActive==2) and (not project[0].isActiveProject()): #nur active projekte
884: returnListTmp.append((depth,nr,title,project[0]))
885:
886:
887: #filter jetzt die Liste nach Archived oder nicht
888: for entry in returnListTmp:
889: if (onlyArchived==0):
890: returnList.append(entry)
891: elif (onlyArchived==1) and (not entry[3].isArchivedProject()): #nur active projekte
892: returnList.append(entry)
893: elif (onlyArchived==2) and (entry[3].isArchivedProject()): #nur active projekte
894: returnList.append(entry)
895:
896:
897: return returnList
898:
899:
900:
901: def changePosition(self,treeId,select,RESPONSE=None):
902: """Change Postion Entry"""
903: numbers=[]
904:
905: # Suche hoechste bisherige nummer
906: projects=self.getProjectFields('xdata_05') # get Projects sorted by xdata_05
907: #print "pj",projects
908: for project in projects: #suche alle subtrees der treeId
909: #print treeId
910:
911: founds=re.match(treeId+"\.(.*)",project[1].split(";")[0])
912: if founds:
913: #print "x",founds.group(0),len(founds.group(0).split("."))
914: if len(founds.group(0).split("."))==len(treeId.split("."))+1: # nur ein punkt mehr, d.h. untere ebene
915: try:
916: numbers.append(int(founds.group(0).split(".")[len(founds.group(0).split("."))-1]))
917: except:
918: numbers.append(int(0))
919:
920: try:
921: highest=max(numbers)
922: except:
923: highest=0
924: projects=self.showNewProjects()
925: for i in self.makeList(select):
926: highest+=10
927: projects[int(i)][0].xdata_05=treeId+"."+str(highest)
928:
929:
930: if RESPONSE is not None:
931: RESPONSE.redirect('showTree')
932:
933: def changeTree(self,RESPONSE=None):
934: """change the complete tree"""
935: form=self.REQUEST.form
936: hashList={}
937: onlyArchived=int(form.get("onlyArchived",0))
938: onlyActive=int(form.get("onlyActive",0))
939:
940:
941: fields=self.getTree(onlyArchived=onlyArchived,onlyActive=onlyActive)
942:
943: logging.info("GOT TREE!----------------------------------------------------")
944: for field in form.keys():
945:
946: splitted=field.split('_')
947: if (len(splitted)>1) and (splitted[1]=="runningNumber"): #feld hat die Form Nummer_name und runnignNumber
948:
949:
950: nr=int(splitted[0]) # nummer des Datensatzes
951: currentEntry = fields[nr]
952:
953: if form.has_key(str(nr)+'_active'): # active flag is set
954: fields[nr][3].setActiveFlag(True)
955: else:
956: fields[nr][3].setActiveFlag(False)
957:
958: #nummer hat sich geŠndert
959:
960: entryChanged = False;
961:
962:
963: if not (fields[nr][3].xdata_05==form[str(nr)+'_number']):
964: logging.info("Changed!Number+++++++++++++++++++++++++++++++++")
965: fields[nr][3].xdata_05=form[str(nr)+'_number']
966: entryChanged = True
967:
968: #completed har sich geaendert
969:
970: if not (fields[nr][3].getCompletedAt()==fields[nr][3].transformDate(form[str(nr)+'_completed'])):
971: fields[nr][3].setCompletedAt(form[str(nr)+'_completed'])
972: logging.info("Changed!Completed+++++++++++++++++++++++++++++++++")
973: entryChanged = True
974:
975:
976: if entryChanged:
977: logging.info("Changed!+++++++++++++++++++++++++++++++++")
978: fields[nr][3].copyObjectToArchive()
979:
980:
981: if RESPONSE is not None:
982: RESPONSE.redirect('showTree')
983:
984: def getProjectWithId(self,id):
985: fields=self.getProjectFields('xdata_05')
986: for field in fields:
987: if field[1]==id:
988: return field[0]
989:
990: return None
991:
992:
993:
994:
995: def getRelativeUrlFromPerson(self,list):
996: """get urls to person list"""
997: ret=[]
998: persons=list.split(";")
999: for person in persons:
1000:
1001: if len(person)>1: #nicht nur Trennzeichen
1002: splitted=person.split(",")
1003: if len(splitted)==1:
1004: splitted=person.split(" ")
1005: splittedNew=[re.sub(r'\s(.*)','$1',split) for split in splitted]
1006: if splittedNew[0]=='':
1007: del splittedNew[0]
1008: search=string.join(splittedNew,' AND ')
1009:
1010: if not search=='':
1011:
1012: try:
1013: proj=self.MembersCatalog({'title':search})
1014: except:
1015: proj=None
1016:
1017: if proj:
1018: #ret.append("<a href=%s >%s</a>"%(proj[0].absolute_url,person.encode('utf-8')))
1019: ret.append("<a href=%s >%s</a>"%('members/'+proj[0].id+'/index.html',person))
1020: else:
1021: #ret.append("%s"%person.encode('utf-8'))
1022: ret.append("%s"%person)
1023: return string.join(ret,";")
1024:
1025: def getMemberIdFromKey(self,key):
1026: """gibt die ensprechende id im members Ordner zum key"""
1027:
1028: if key=="":
1029: return ""
1030: catalogged=self.MembersCatalog({'getKey':key})
1031: if len(catalogged)==0:
1032: return ""
1033: else:
1034: return catalogged[0].getObject().getId()
1035:
1036:
1037:
1.1.2.2 ! dwinter 1038:
1.1.2.1 dwinter 1039: def getProjectsOfMembers(self,date=None):
1040: """give tuple member /projects"""
1041: ret=[]
1042: members=self.getAllMembers()
1043:
1044: #return str(members)
1045: for x in members:
1046: projects=self.getProjectsOfMember(key=x[1],date=date)
1047: if len(projects)>0:
1048: ret.append((x[0],projects))
1049:
1050: return ret
1051:
1052: def getProjectsOfMember(self,key=None,date=None,onlyArchived=1,onlyActive=1):
1053: """get projects of a member
1054:
1055: @param key: (optional) Key zur Idenfikation des Benutzer
1056: @param date: (optional) Version die zum Zeitpunkt date gueltig war
1057: @param onlyArchived:
1058: onlyArchived=0: alle Projekte
1059: onlyArchived= 1 : nur aktuelle Projekte
1060: onlyArchived = 2: nur archivierte Projekte
1061: """
1062: # TODO: Die ganze Loesung
1063: def sortP(x,y):
1064: """sort by sorting number"""
1065: return cmp(x.WEB_title,y.WEB_title)
1066:
1067: ret=[]
1068: if key:
1069: proj=self.ProjectCatalog({'getPersonKeyList':key})
1070: else:
1071: return ret # key muss definiert sein
1072:
1073:
1074: if proj:
1075: proj2=[]
1076: for x in proj:
1077: if (not getattr(x.getObject(),'invisible',None)) and (getattr(x.getObject(),'archiveTime','')==''):
1078: proj2.append(x)
1079:
1080: else:
1081: proj2=[]
1082:
1083:
1084:
1085: proj2.sort(sortP)
1086:
1087: projectListe=[]
1088:
1089: for proj in proj2:
1090: obj=proj.getObject()
1091: add=False
1092: if onlyArchived==1: #nur aktuell projecte
1093: if not obj.isArchivedProject():
1094: add=True
1095: elif onlyArchived==2: #nur archivierte
1096: if obj.isArchivedProject():
1097: add=True
1098: else: #alle
1099: add=True
1100:
1101: if onlyActive==1: #nur active projecte
1102: if obj.isActiveProject():
1103: add=add & True
1104: else:
1105: add=add & False
1106:
1107: elif onlyArchived==2: #nur nicht aktvive
1108: if not obj.isActiveProject():
1109: add=add & True
1110: else: #alle
1111: add=add & True
1112:
1113: if add:
1114: projectListe.append(obj)
1115:
1116:
1117: return projectListe
1118:
1119: def givePersonList(self,name):
1120: """check if person is in personfolder and return list of person objects"""
1121:
1122: splitted=name.split(",")
1123: if len(splitted)==1:
1124: splitted=name.lstrip().rstrip().split(" ")
1125: splittedNew=[split.lstrip() for split in splitted]
1126:
1127: if splittedNew[0]=='':
1128: del splittedNew[0]
1129: search=string.join(splittedNew,' AND ')
1130:
1131: if not search=='':
1132: proj=self.MembersCatalog({'title':search})
1133:
1134: if proj:
1135: return [[x.lastName,x.firstName] for x in proj]
1136: else:
1137: return []
1138:
1139: ## splitted=name.split(",") # version nachname, vorname...
1140: ## if len(splitted)>1:
1141: ## lastName=splitted[0]
1142: ## firstName=splitted[1]
1143: ## else:
1144: ## splitted=name.split(" ") #version vorname irgenwas nachnamae
1145:
1146: ## lastName=splitted[len(splitted)-1]
1147: ## firstName=string.join(splitted[0:len(splitted)-1])
1148:
1149: ## objs=[]
1150:
1151: #print self.members
1152: ## for x in self.members.__dict__:
1153: ## obj=getattr(self.members,x)
1154: ## if hasattr(obj,'lastName') and hasattr(obj,'firstName'):
1155:
1156: ## if (re.match(".*"+obj.lastName+".*",lastName) or re.match(".*"+lastName+".*",obj.lastName)) and (re.match(".*"+obj.firstName+".*",firstName) or re.match(".*"+firstName+".*",obj.firstName)):
1157:
1158: ## objs.append((obj,lastName+", "+firstName))
1159:
1160:
1161: ## return objs
1162:
1163:
1164: def personCheck(self,names):
1165: """all persons for list"""
1166: #print "names",names
1167: splitted=names.split(";")
1168: ret={}
1169: for name in splitted:
1170:
1171: if not (name==""):
1172: try:
1173: ret[name]=self.givePersonList(name)
1174: except:
1175: """NOTHIHN"""
1176: #print "RET",ret
1177: return ret
1178:
1179: def giveCheckList(self,person,fieldname):
1180: """return checklist"""
1181: #print "GCL",fieldname
1182: if fieldname=='xdata_01':
1183: x=self.personCheck(person.getContent(fieldname))
1184: #print "GCLBACKX",x
1185: return x
1186:
1187:
1188: def isCheckField(self,fieldname):
1189: """return chechfield"""
1190:
1191: return (fieldname in checkFields)
1192:
1193:
1194: def generateNameIndex(self):
1195: """erzeuge einen index verwendeter personen"""
1196: import psycopg
1197: o = psycopg.connect('dbname=authorities user=dwinter password=3333',serialize=0)
1198: results={}
1199: print self.fulltext.historicalNames.items()
1200: for nameItem in self.fulltext.historicalNames.items(): #gehe durch alle namen des lexikons
1201:
1202: c = o.cursor()
1203: name=nameItem[0]
1204: print "check",name
1205: c.execute("select lastname,firstname from persons where lower(lastname) = '%s'"%quote(name))
1206: tmpres=c.fetchall()
1207: firstnames=[result[1] for result in tmpres] # find all firstnames
1208: if tmpres:
1209: lastname=tmpres[0][0]
1210:
1211: for found in self.fulltext({'names':name}):
1212: if found.getObject().isActual():
1213: for nh in found.getObject().getGetNeighbourhood(name, length=50,tagging=False): #hole umgebung
1214: #schaue nun ob der vorname hinter oder vor dem name ist
1215: position=nh.find(lastname)
1216: # vorher
1217: #print "NH",nh
1218: bevorS=nh[0:position].split()
1219: #print "BV",bevorS
1220: if len(bevorS)>1:
1221: try:
1222: bevor=[bevorS[-1],bevorS[-2]]
1223: except:
1224: bevor=[bevorS[0]]
1225: else:
1226: bevor=[]
1227: #nachher
1228: behindS= re.split("[,|;| ]",nh[position:])
1229: #print "BH",behindS
1230: if len(behindS)>2:
1231: try:
1232: behind=behindS[1:3]
1233: except:
1234: behind=[bevorS[1]]
1235: else:
1236: behind=[]
1237: for firstname in firstnames:
1238: if firstname in bevor+behind: #Namen wie mit Adelspraedikaten werden so erstmal nich gefunden
1239: id="%s,%s"%(lastname,firstname)
1240: if not results.has_key(id):
1241: results[id]=[]
1242: objId=found.getObject().getId()
1243: if not (objId in results[id]):
1244: print "d %s for %s"%(id,objId)
1245: results[id].append(objId)
1246: self.nameIndex=results
1247: return results
1248:
1249: def editNameIndexHTML(self):
1250: """edit the name index"""
1251: if not hasattr(self,'nameIndexEdited'): # falls editierter index noch nicht existiert, kopiere automatisch erstellten
1252: self.nameIndexEdited=copy.copy(self.nameIndex)
1253: print "huh"
1254: #self.nameIndexEdited=copy.copy(self.nameIndex)
1255: #print self.nameIndexEdited
1256: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','editHistoricalNames.zpt')).__of__(self)
1257: return pt()
1258:
1259: def getNamesInProject(self,projectId):
1260: """get all names ofnameIndexEdited which are references in projec with projectId"""
1261:
1262: ret=[]
1263: for name in self.nameIndexEdited.keys():
1264: if projectId in self.nameIndexEdited[name]:
1265: ret.append(name)
1266:
1267: return ret
1268:
1269: def editNameIndex(self,RESPONSE=None,name=None,occurrances=None,submit=None):
1270: """edit the index"""
1271: nI=self.nameIndexEdited # mI introduced to make sure that changes to nameIndexEdited are know to ZODB
1272: if submit=="delete":
1273:
1274:
1275: dh=getattr(self,'deletedHistoricalNames',{})
1276:
1277: if type(dh) is ListType:
1278: dh={}
1279: if not dh.has_key(name):
1280: dh[name]=occurrances.split("\n")
1281: else:
1282: dh[name]+=occurrances.split("\n")
1283:
1284: self.deletedHistoricalNames=dh
1285:
1286: del self.nameIndexEdited[name]
1287:
1288:
1289: elif (submit=="change"):
1290:
1291: nI[name]=occurrances.split("\n")[0:]
1292:
1293: elif (submit=="add"):
1294: if not nI.has_key(name):
1295: nI[name]=occurrances.split("\n")
1296: else:
1297: nI[name]+=occurrances.split("\n")
1298:
1299: self.nameIndexEdited=nI
1300:
1301:
1302: if RESPONSE is not None:
1303: RESPONSE.redirect('editNameIndexHTML')
1304:
1305:
1306:
1307: def restoreIndex(self):
1308: """restore"""
1309: self.nameIndexEdited=self.nameIndex
1310: return "done"
1311:
1312:
1313:
1314: def manage_addMPIWGRootForm(self):
1315: """form for adding the root"""
1316: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMPIWGRootForm.zpt')).__of__(self)
1317: return pt()
1318:
1319: def manage_addMPIWGRoot(self,id,title,connection_id="",RESPONSE=None):
1320: """add a root folder"""
1321: newObj=MPIWGRoot(id,title)
1322: self._setObject(id,newObj)
1323: ob=getattr(self,id)
1324: setattr(ob,'connection_id',connection_id)
1325: if RESPONSE is not None:
1326: RESPONSE.redirect('manage_main')
1327:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>