1: """This contains the class MPIWG Projects
2: for organizing and maintaining the different project pages
3:
4: $author dwinter - last change 26.06.2008
5:
6: """
7: from Products.PageTemplates.PageTemplateFile import PageTemplateFile
8: from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
9: from Products.ZCatalog.CatalogPathAwareness import CatalogAware
10: from Products.MPIWGBibliography.BibliographyManager import BibliographyManager
11: from OFS.Image import Image
12: from Globals import package_home
13: import urllib
14: import re
15: import os
16: import email
17: from types import *
18: import logging
19: import xmlhelper # Methoden zur Verwaltung der projekt xml
20: from OFS.SimpleItem import SimpleItem
21: from OFS.Folder import Folder
22: from OFS.Image import Image
23: from AccessControl import ClassSecurityInfo
24: from AccessControl import getSecurityManager
25: from bibliography import *
26: import time
27: from OFS.Cache import Cacheable
28: #import xml.dom.minidom
29: import sys
30: #from Ft.Xml.XPath import Evaluate
31: #from Ft.Xml.XPath.Context import Context
32: #from Ft.Xml.Domlette import NonvalidatingReader,PrettyPrint, Print
33: #from Ft.Xml import EMPTY_NAMESPACE
34: #import copy
35: #import updatePersonalWWW
36:
37: #import MPIWGStaff
38:
39: from MPIWGHelper import *
40:
41: import MPIWGRoot
42: import MPIWGLink
43: import MPIWGTemplate
44:
45: # die folgenden Klassen sind jetzt in einzelne Files ausgelagert aus Kompatibilitaetsgruenden, bleiben die Klassen hier noch drin.
46: # Sonst funktionieren die alten Webseiten nicht mehr.
47:
48: class MPIWGRoot(MPIWGRoot.MPIWGRoot):
49: """depricated"""
50:
51: class MPIWGLink(MPIWGLink.MPIWGLink):
52: """depricated"""
53:
54: class MPIWGTemplate(MPIWGTemplate.MPIWGTemplate):
55: """depricated"""
56:
57: class MPIWGProject_publication(Folder):
58: """publications object fuer project"""
59:
60: meta_type="MPIWGProject_publication"
61: def redirect(self,RESPONSE,url):
62: """mache ein redirect mit einem angehaengten time stamp um ein reload zu erzwingen"""
63:
64: timeStamp=time.time()
65:
66: if url.find("?")>-1: #giebt es schon parameter
67: addStr="&time=%s"
68: else:
69: addStr="?time=%s"
70:
71: RESPONSE.setHeader('Last-Modified',email.Utils.formatdate().split("-")[0]+'GMT')
72: logging.debug(email.Utils.formatdate()+' GMT')
73: RESPONSE.redirect(url+addStr%timeStamp)
74:
75: def editPublication(self,text=None,image1=None,image2=None,description=None,RESPONSE=None):
76: """edit a publication"""
77:
78: if (not text) and (not description):
79: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_publicationForm.zpt')).__of__(self)
80: return pt()
81:
82:
83: self.text=text[0:]
84: self.description=description
85:
86: if image1:
87: if hasattr(self,'publicationImage1'):
88: self.publicationImage1.manage_upload(image1)
89: else:
90: nO = Image('publicationImage1','',image1)
91: self._setObject('publicationImage1',nO)
92:
93: if image2:
94: if hasattr(self,'publicationImage2'):
95: self.publicationImage2.manage_upload(image2)
96: else:
97: nO = Image('publicationImage2','',image2)
98: self._setObject('publicationImage2',nO)
99:
100:
101: if RESPONSE:
102: self.redirect(RESPONSE,"../managePublications")
103:
104: class MPIWGProject_image(Image):
105: """Images for Projects"""
106:
107: meta_type="MPIWGProject_image"
108:
109: def showImage(self,imageUrl=None):
110: """show Images at an extra page"""
111: self.getContent('WEB_project_description',filter='yes') #get the content and store image infos into session
112: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','projectImageView.zpt')).__of__(self)
113: return pt()
114:
115: def editImage(self,file=None,caption=None,RESPONSE=None):
116: """edit the Image"""
117: if (not file) and (not caption):
118: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_imageForm.zpt')).__of__(self)
119: return pt()
120:
121: if file and (not file.filename.lstrip().rstrip()==""):
122: self.manage_upload(file)
123:
124: if caption:
125: self.caption=caption[0:]
126:
127: if RESPONSE:
128:
129: self.redirect(RESPONSE,"../manageImages")
130:
131: class MPIWGProject(CatalogAware,Folder,Cacheable):
132: """Class for Projects"""
133:
134: def _p_resolveConflict(self, oldState, savedState, newState):
135: return newState
136:
137: security=ClassSecurityInfo()
138: meta_type='MPIWGProject'
139: default_catalog='ProjectCatalog'
140: def redirect(self,RESPONSE,url):
141: """mache ein redirect mit einem angehaengten time stamp um ein reload zu erzwingen"""
142:
143: timeStamp=time.time()
144:
145: if url.find("?")>-1: #giebt es schon parameter
146: addStr="&time=%s"
147: else:
148: addStr="?time=%s"
149:
150: RESPONSE.setHeader('Last-Modified',email.Utils.formatdate().split("-")[0]+'GMT')
151: logging.debug(email.Utils.formatdate()+' GMT')
152: RESPONSE.redirect(url+addStr%timeStamp)
153:
154: def decode(self,str):
155: """return unicode object"""
156: return unicodify(str)
157:
158: def sortedByPlace(self,metatype):
159: """find metatype and sort by place"""
160: def sort(x,y):
161: return cmp(getattr(x[1],'place',0),getattr(y[1],'place',0))
162:
163: founds=self.ZopeFind(self,obj_metatypes=[metatype]);
164:
165: founds.sort(sort)
166:
167: return founds
168:
169:
170: def copyPublicationsToList(self,RESPONSE=None):
171: """copy publications in to list"""
172:
173: publicationTxt=self.getContent('WEB_related_pub')
174:
175: pubSplits=publicationTxt.split("<p>")
176:
177: for pubSplit in pubSplits:
178: pubSplit=pubSplit.replace("</p>","")
179: self.addPublication(pubSplit)
180:
181: if RESPONSE:
182:
183: self.redirect(RESPONSE,'managePublications')
184:
185:
186: def copyImageToMargin(self,RESPONSE=None):
187: """copy inline images to marginal images"""
188:
189:
190: #getImages from WEB_project_description
191: description=self.getContent('WEB_project_description')
192:
193: text2=description
194: splitted=text2.split("""<p class="picture">""")
195:
196: imageURLs=[]
197: imageCaptions=[]
198: for split in splitted[1:]:
199: tmp=split.split("</p>")
200: #return repr(splitted[1])
201:
202: try:
203: imageURLs.append(tmp[0].split("\"")[1].encode('utf-8'))
204: except:
205:
206: try:
207: imageURLs.append(tmp[0].split("src=")[1].split(" ")[0].encode('utf-8'))
208: except:
209: imageURLs.append("")
210:
211: split2="</p>".join(tmp[1:])
212:
213:
214: splitted=split2.split("""<p class="picturetitle">""")
215: if len(splitted)>1:
216: tmp=splitted[1].split("</p>")
217: imageCaptions.append(tmp[0].encode('utf-8'))
218:
219:
220: else:
221: #keine caption
222:
223: imageCaptions.append("")
224:
225:
226: #eintragen:
227: for imageURL in imageURLs:
228: filename=imageURL.split("/")[-1]
229: #lege neues images object an, mit leerem bild
230:
231: if self.ZopeFind(self,obj_ids=[filename]):
232: #existiert das bild schon, dann neuen filenamen
233: filename="project_image_"+filename
234:
235: self.addImage(None,imageCaptions[imageURLs.index(imageURL)],filename=filename)
236: #hole die bilddaten aus der url
237: url=self.absolute_url()+"/"+imageURL
238: #url=self.absolute_url()+"/"+filename
239:
240: try:#relative url
241: data=urllib.urlopen(url).read()
242: except:
243: try:#absolute
244: data=urllib.urlopen(self.imageURL).read()
245: except:
246: logger("MPIWG Project",logging.ERROR,"can't open: %s"%url)
247:
248: obj=getattr(self,filename)
249: obj.update_data(data)
250:
251: if RESPONSE:
252:
253: self.redirect(RESPONSE,'manageImages')
254:
255: def manageImages(self,imageName=None,op=None):
256: """managage images"""
257:
258:
259: if imageName and op:
260: if op=='up':
261: images=self.getImages()
262: for image in images:
263: if image[0]==imageName:
264: nr=images.index(image)
265: if not nr==0:
266: images[nr-1][1].place+=1
267: images[nr][1].place-=1
268: pass
269: elif op=='down':
270: images=self.getImages()
271: for image in images:
272: if image[0]==imageName:
273: nr=images.index(image)
274: if not (nr==len(images)-1):
275: images[nr+1][1].place-=1
276: images[nr][1].place+=1
277: pass
278:
279:
280: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','MPIWGProject_manageImagesForm.zpt')).__of__(self)
281: return pt()
282:
283: def managePublications(self,pubName=None,op=None):
284: """managage images"""
285:
286:
287: if pubName and op:
288: if op=='up':
289: publications=self.getPublications()
290: for publication in publications:
291: if publication[0]==pubName:
292: nr=publications.index(publication)
293: if not nr==0:
294: publications[nr-1][1].place+=1
295: publications[nr][1].place-=1
296: pass
297: elif op=='down':
298: publications=self.getPublications()
299: for publication in publications:
300: if publication[0]==pubName:
301: nr=publications.index(publication)
302: if not (nr==len(publications)-1):
303: publications[nr+1][1].place-=1
304: publications[nr][1].place+=1
305: pass
306:
307:
308: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','MPIWGProject_managePublicationsForm.zpt')).__of__(self)
309: return pt()
310: def hasExtendedPublicationList(self):
311: """test if extended publication list exists"""
312: if not hasattr(self,"publicationList"):
313: return False
314: else:
315: return True
316:
317: def createExtendedPublicationList(self,RESPONSE=None):
318: """erzeuge erweiterte publications liste"""
319: pl = BibliographyManager("publicationList","","institutsbiblio",self.connection_id)
320: self._setObject("publicationList", pl)
321:
322:
323: zt=ZopePageTemplate('index.html')
324: pl._setObject('index.html',zt)
325: default_content_fn = os.path.join(package_home(globals()),
326: 'zpt/showExtendedProjectBibliography.zpt')
327: text = open(default_content_fn).read()
328: zt.pt_edit(text, 'text/html')
329:
330:
331: if RESPONSE:
332: self.redirect(RESPONSE,"managePublications")
333:
334:
335: def getPublications(self):
336: """get all Publications"""
337: def sort_images(x,y):
338: return cmp(getattr(x[1],'place',0),getattr(y[1],'place',0))
339:
340: publications=self.ZopeFind(self,obj_metatypes=['MPIWGProject_publication'])
341:
342: publications.sort(sort_images)
343: return publications
344:
345: def addPublication(self,text,RESPONSE=None):
346: """add an MPIWG_Publication"""
347:
348: name="publication_"+str(self.getLastPublicationNumber()+1)
349:
350: newPublication=MPIWGProject_publication(name)
351:
352: self._setObject(name,newPublication)
353: obj=getattr(self,name)
354: obj.text=text[0:]
355: obj.enabled=True;
356: obj.place=self.getLastPublicationNumber()+1
357: obj.id=name
358:
359: if RESPONSE is not None:
360:
361: self.redirect(RESPONSE,'managePublications')
362:
363:
364: def getLastPublicationNumber(self):
365: publications=self.getPublications()
366:
367: if not publications:
368: return 0
369: else:
370: return getattr(publications[-1][1],'place',0)
371:
372: def deletePublication(self,id,RESPONSE=None):
373: """delete Publication id"""
374: self.manage_delObjects([id])
375: if RESPONSE:
376:
377: self.redirect(RESPONSE,'managePublications')
378:
379: def getImages(self):
380: """get all Images"""
381:
382: def sort_images(x,y):
383: return cmp(getattr(x[1],'place',0),getattr(y[1],'place',0))
384:
385:
386: if (getattr(self,'imageURL','')!='') or (getattr(self,'imagecap','')!='') :
387: try:
388: self.addImage(None,getattr(self,'imagecap',''),RESPONSE=None,filename=getattr(self,'imageURL',''))
389: except:
390: pass
391: self.imageURL=''
392: self.imagecap=''
393:
394: images=self.ZopeFind(self,obj_metatypes=['MPIWGProject_image'])
395:
396: images.sort(sort_images)
397: return images
398:
399: def getLastImageNumber(self):
400: images=self.getImages()
401:
402: if not images:
403: return 0
404: else:
405: return getattr(images[-1][1],'place',0)
406:
407: def deleteImage(self,id,RESPONSE=None):
408: """delete Image id"""
409: try:
410: self.manage_delObjects([id])
411: except:
412: logging.error("ERROR MPIWG: %s %s"%sys.exc_info()[0:2])
413: if RESPONSE:
414: self.redirect(RESPONSE,'manageImages')
415:
416:
417:
418: def hasChildren(self,date=None,onlyActive=1,onlyArchived=1):
419: """check if project has children"""
420:
421: ct=self.getContexts(childs=self.getContent('xdata_05'),
422: depth=1,date=date,onlyActive=onlyActive)
423:
424: if ct and len(ct)>0:
425: return True
426: else:
427: return False
428:
429:
430: def addImage(self,fileHd,caption,RESPONSE=None,filename=None):
431: """add an MPIWG_Project_image"""
432:
433: if not filename:
434: filename=fileHd.filename
435:
436: if not fileHd:
437: fileHd=file(os.path.join(package_home(globals()),'blank.gif'))
438:
439: newImage=MPIWGProject_image(filename,filename,fileHd)
440:
441: self._setObject(filename,newImage)
442: obj=getattr(self,filename)
443: obj.caption=caption[0:]
444: obj.enabled=True;
445: obj.place=self.getLastImageNumber()+1
446: obj.id=filename
447:
448: if RESPONSE is not None:
449:
450: self.redirect(RESPONSE,'manageImages')
451:
452: def PrincipiaSearchSource(self):
453: """Return cataloguable key for ourselves."""
454: return str(self)
455:
456: def versionHeader(self):
457: """version Header, gibt header text entsprechend der aktuellen version aus"""
458:
459: actualTime=time.localtime()
460: retTXT="""<h2>This is an outdated version, for the actual version please refer to <a href="%s">%s</a></h2>"""
461: s=self.aq_parent.absolute_url()
462: #print getattr(self,'archiveTime',actualTime)
463: if getattr(self,'archiveTime',actualTime)< actualTime:
464: return retTXT%(s,s)
465: else:
466: return ""
467:
468: def getActualVersion(self,date=None):
469: """actuelle version"""
470: def sortProjectsByTime(x,y):
471: return cmp(x[1].archiveTime,y[1].archiveTime)
472:
473: if not date:
474: if self.isActual():
475: return self
476: else:
477: return None
478:
479: #suche ob aeltere versionen vorhanden sind
480:
481: finds=self.ZopeFind(self,obj_metatypes=['MPIWGProject'])
482: if not finds: #wenn nicht dann teste ob die aktuelle version schon existiert hat.
483: ad=getattr(self,'creationTime','20050101000000')
484: if int(date)>int(ad):
485: return self
486: else:
487: return None
488:
489:
490: else:
491: finds.sort(sortProjectsByTime)
492:
493: for find in finds:
494: #gehe durch die alten Projekte und finde das entprechende
495: if (int(find[1].archiveTime) > int(date)) and (int(date)>int(getattr(find[1],'creationTime','20050101000000'))):
496: return find[1]
497:
498: #kein passendes gefunden, dann teste ob das aktuelle in frage kommt
499: ad=getattr(self,'creationTime','20050101000000')
500:
501: if int(date)>int(ad):
502:
503: return self
504: else:
505: return None
506:
507:
508: def isActual(self):
509: """gibt 1 zurueck wenn aktuell, 0 sonst"""
510: actualTime=time.localtime()
511:
512:
513: #print getattr(self,'archiveTime',actualTime)
514: if getattr(self,'archiveTime',actualTime)< actualTime:
515: return 0
516: else:
517: return 1
518:
519: def copyObjectToArchive(self):
520: """kopiere aktuelles objekt ins archiv"""
521: cb=self.aq_parent.manage_copyObjects(self.getId())
522: self.manage_pasteObjects(cb)
523: actualTime=time.localtime()
524:
525: self.manage_renameObject(self.getId(),self.getId()+"_"+time.strftime("%Y%m%d%H%M%S",actualTime))
526: obj=getattr(self,self.getId()+"_"+time.strftime("%Y%m%d%H%M%S",actualTime))
527: obj.setArchiveTime(time.strftime("%Y%m%d%H%M%S",actualTime))
528: ids=[x[0] for x in self.ZopeFind(obj,obj_metatypes=['MPIWGProject'])]
529: obj.manage_delObjects(ids)
530:
531: def setArchiveTime(self,time):
532: """set Archive Time"""
533: self.archiveTime=time[0:]
534:
535: def delArchiveTime(self):
536: """delete archive time"""
537: del self.archiveTime
538:
539: def versionManageForm(self):
540: """version Manage form:currently only set to invisible"""
541: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','MPIWGProject_versionManageForm.zpt')).__of__(self)
542: return pt()
543:
544: def versionManage(self,invisible=None,RESPONSE=None):
545: """version Manage form:currently only set to invisible"""
546: self.invisible=invisible
547:
548: if RESPONSE is not None:
549:
550: self.redirect(RESPONSE,'manage_main')
551:
552:
553: def crossLinker(self):
554: """experimental crosslinker"""
555: splitted=self.WEB_project_description[0].split()
556: new=[]
557: for split in splitted:
558: try:
559: found=self.DescriptionCatalog({'fulltext':split})
560:
561: if len(found)>1:
562:
563: new.append("<a href=%s>%s</a>"%(split,split))
564: else:
565: new.append(split)
566: except:
567: new.append(split)
568: return " ".join(new)
569:
570:
571:
572:
573: def generateTemplate(self,RESPONSE=None):
574: """Erzeuge Template fuer defined fields not_used"""
575:
576: id="index_html"
577: title=id
578: if self._getOb('index_html'):
579: self._delObject('index_html')
580:
581:
582: newObj=ZopePageTemplate(id,'TEXT')
583: self._setObject(id,newObj)
584: #self.manage_addPageTemplate(id,title)
585: if RESPONSE is not None:
586: self.redirect(RESPONSE,'manage_main')
587:
588: def __init__(self, id, argv=None):
589: """initiere classe"""
590:
591: self.creationTime=time.strftime("%Y%m%d%H%M%S",time.localtime())[0:]
592: self.id=id
593: self.title=id
594: self.isActiveFlag=True #Flag is true is the project is still active, False if accomplished
595: self.responsibleScientistsList=[] # enthaelt die Lister der verantwortlichen Wissenschaftler in der Form (NAME, KEY), key ist "" flass Wissenschaftler nicht an unserem Haus
596:
597: if argv:
598: for arg in definedFields:
599: try:
600: setattr(self,arg,argv[arg])
601: except:
602: setattr(self,arg,"")
603: else:
604: for arg in definedFields:
605: setattr(self,arg,'')
606:
607: manage_options = Folder.manage_options+(
608: {'label':'Load New File','action':'loadNewFileForm'},
609: {'label':'Edit ProjectInfo','action':'editMPIWGProjectForm'},
610: {'label':'Edit BasisInfo','action':'editMPIWGBasisForm'},
611: {'label':'Edit Publications','action':'editMPIWGRelatedPublicationsForm'},
612: {'label':'Edit Themes & Disciplines','action':'editMPIWGDisciplinesThemesForm'},
613: {'label':'Versionmanager','action':'versionManageForm'},
614: )
615:
616:
617: def isActiveProject(self):
618: """check if the project is still active, default is true, set to false is the project is accomplished"""
619: return getattr(self,'isActiveFlag',True)
620:
621: def isArchivedProject(self):
622: """check if the project is archived"""
623:
624: completed=self.getCompletedAt()
625:
626: #completed leer
627: if completed=="" :
628: return False;
629: if completed == 0:
630: return False;
631:
632:
633: return True
634:
635:
636: def setActiveFlag(self,status=True):
637: """set the active flag"""
638: self.isActiveFlag=status
639:
640: def setCompletedAt(self,date):
641: """set the date of completion, date should be in the form DD.MM.YYYY or MM.YYYY or YYYY"""
642: #logging.info("DATE:"+repr(date))
643: transformedDate=self.transformDate(date);
644: #logging.info("transformed"+repr(transformedDate))
645: if transformedDate is not None:
646: setattr(self,"completedAt",transformedDate)
647: return True;
648: else:
649: return False;
650:
651: def setStartedAt(self,date):
652: """set the date of start, date should be in the form DD.MM.YYYY or MM.YYYY or YYYY"""
653: #logging.info("DATE:"+repr(date))
654: transformedDate=self.transformDate(date);
655: #logging.info("transformed"+repr(transformedDate))
656: if transformedDate is not None:
657: setattr(self,"startedAt",transformedDate)
658: return True;
659: else:
660: return False;
661:
662: def getCompletedAt(self):
663: """gibt das transformierte Datum zurueck, an dem das Projekt beendet wurde."""
664: date=getattr(self,'completedAt','')
665:
666: if date:
667: return self.reTransformDate(date);
668: else:
669: return ""
670: # test ob parent abgeschlossen ist
671: try: #TODO: ersetzte try except durch vernuenftige abfrage
672: ct=self.getContexts(parents=self.getContent('xdata_05'),depth=1)
673: if (len(ct)>0): #is there are parent
674: return ct[0][0].getCompletedAt()
675: return '';
676: except:
677: return '';
678:
679: def getStartedAt(self):
680: """gibt das transformierte Datum zurueck, an dem Projekt begonnen wurde."""
681: date=getattr(self,'startedAt','')
682: if date:
683: return self.reTransformDate(date);
684: else:
685: return '';
686:
687: def reTransformDate(self,date):
688: """transformiert , transformdate zurueck"""
689: year=int(date/10000)
690: month=int((date-year*10000)/100)
691: day=int((date-year*10000-month*100))
692: if (day==0) and (month==0):
693: return """%s"""%year;
694: if day==0 :
695: return """%s.%s"""%(month,year);
696:
697: return """%s.%s.%s"""%(day,month,year);
698:
699:
700: def transformDate(self,date):
701: """transformiert ein Datum von DD.MM.YYYY, MM.YYYY,YYYY nach YYYYMMDD, alle nicht angebenen Werte
702: werden auf 0 gesetzt, es wird null zurueckgegeben falls das Datum ungueltig ist"""
703:
704: if (date==None):
705: return None;
706:
707:
708: if (date.lstrip().rstrip()=="" ) :
709: return "";
710:
711: splitted=date.split(".")
712: length=len(splitted)
713: year=0
714: month=0
715: day=0
716: if length > 3:
717: return "";
718: if length==3:
719: day = int(splitted[0])
720: if length>1:
721: month=int(splitted[length-2])
722:
723: if length > 0:
724: try:
725: year = int(splitted[length-1])
726: except:
727: pass
728:
729: ## logging.info("month:"+(month))
730: if not (0<=month<13):
731: return None;
732:
733: if not(0<=day<32):
734: return None;
735:
736: if (year>0) and (year<1900): #jahr nicht vierstellig eingegeben
737: year=2000+year;
738: return year*10000+month*100+day
739:
740:
741:
742: def checkDate(self,date):
743: """teste ob zum Zeitpunkt date eine andere version existierte"""
744:
745:
746: def sortProjectsByTime(x,y):
747: return cmp(x[1].archiveTime,y[1].archiveTime)
748:
749: #suche ob aeltere versionen vorhanden sind
750:
751: finds=self.ZopeFind(self,obj_metatypes=['MPIWGProject'])
752: if not finds: #wenn nicht dann teste ob die aktuelle version schon existiert hat.
753: ad=getattr(self,'creationTime','20050101000000')
754: if int(date)>int(ad):
755: return self.REQUEST['URL1']+"/"+self.getId()
756: else:
757: return self.REQUEST['URL1']+"/no_project"
758:
759:
760: else:
761: finds.sort(sortProjectsByTime)
762:
763: for find in finds:
764: #gehe durch die alten Projekte und finde das entprechende
765: if (int(find[1].archiveTime) > int(date)) and (int(date)>int(getattr(find[1],'creationTime','20050101000000'))):
766: return self.REQUEST['URL1']+"/"+find[1].getId()
767:
768: #kein passendes gefunden, dann teste ob das aktuelle in frage kommt
769: ad=getattr(self,'creationTime','20050101000000')
770:
771: if int(date)>int(ad):
772:
773: return self.REQUEST['URL1']+"/"+self.getId()
774: else:
775: return self.REQUEST['URL1']+"/no_project"
776:
777:
778: def no_project(self):
779: """warnung: project noch nicht existent"""
780: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','no_project')).__of__(self)
781: return pt()
782:
783:
784: def harvest_page(self,context=None):
785: """seite fuer harvesting fuer die Projektsuche"""
786: if not context:
787: context=self
788:
789: if self.isActiveProject() and self.isActual():
790: ext=getattr(self,"harvest_main",None)
791: if ext:
792: return getattr(self,ext.getId())()
793:
794: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','harvest_main')).__of__(context)
795:
796:
797: return pt()
798:
799: def index_html(self,request=True,context=None):
800: """show homepage"""
801:
802: bound_names={}
803:
804: if not context:
805: context=self
806: if request:
807: if self.REQUEST.has_key('date') and self.REQUEST.SESSION.get('MPI_redirected',None)==None:
808: self.REQUEST.SESSION['MPI_redirected']=1
809: self.REQUEST.RESPONSE.redirect(self.checkDate(self.REQUEST['date'])+"?date="+self.REQUEST['date'])
810: else:
811: self.REQUEST.SESSION['MPI_redirected']=None
812:
813: #ext=self.ZopeFind(self.aq_parent,obj_ids=["project_main"])
814:
815:
816: request2=getattr(self,'REQUEST',None)
817:
818: if request2 is not None:
819: response = request2.response
820: if not response.headers.has_key('content-type'):
821: response.setHeader('content-type', 'text/html')
822:
823: security = getSecurityManager()
824: bound_names['user'] = security.getUser()
825:
826:
827: # Retrieve the value from the cache.
828: keyset = None
829: if self.ZCacheable_isCachingEnabled():
830:
831: # Prepare a cache key.
832: keyset = {'here': self, 'params':request2['QUERY_STRING']}
833:
834: result = self.ZCacheable_get(keywords=keyset)
835:
836: if result is not None:
837: # Got a cached value.
838: return result
839:
840: pt = getTemplate(self, "project_main")
841: # Execute the template in a new security context.
842: security.addContext(self)
843:
844: try:
845: result = pt.pt_render(extra_context=bound_names)
846: if keyset is not None:
847: # Store the result in the cache.
848: self.ZCacheable_set(result, keywords=keyset)
849:
850: return result
851: finally:
852: security.removeContext(self)
853:
854:
855:
856: def index_html_old(self,request=True,context=None):
857: """show homepage"""
858: if not context:
859: context=self
860: if request:
861: if self.REQUEST.has_key('date') and self.REQUEST.SESSION.get('MPI_redirected',None)==None:
862: self.REQUEST.SESSION['MPI_redirected']=1
863: self.REQUEST.RESPONSE.redirect(self.checkDate(self.REQUEST['date'])+"?date="+self.REQUEST['date'])
864: else:
865: self.REQUEST.SESSION['MPI_redirected']=None
866:
867: #ext=self.ZopeFind(self.aq_parent,obj_ids=["project_main"])
868:
869: ext=getattr(self,"project_main",None)
870: if ext:
871: return getattr(self,ext.getId())()
872:
873: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','project_main')).__of__(context)
874:
875: return pt()
876:
877:
878: def getDataFields(self):
879: """giveListofDatafields"""
880: ret=[]
881: for x in range(1,14):
882: if not x in [6,10,9]: # not used fields
883: ret.append('xdata_%02i'%x)
884: return ret
885:
886: def getDefinedFields(self):
887: """show all defined fields"""
888:
889: return definedFields
890:
891: def getAttribute(self,field):
892: """get attrbiute"""
893: return getattr(self,field)
894:
895: def getContent(self,field,filter=None):
896: """Inhalt des Feldes"""
897:
898: if field=="short_title":
899: text = self.getContent("xdata_07")
900: if text=="":
901: text = self.getContent("WEB_title")
902: return text
903:
904: text=u''
905:
906: for x in getattr(self,field):
907:
908: try:
909: text +=x
910: except:
911: text = x
912:
913:
914:
915: try:
916: if text[len(text)-1]==";":
917: text=text[0:len(text)-1]
918:
919:
920: except:
921: pass
922:
923: if text=='': ## wozu die folgenden Zeilen??
924: text2=text
925: else:
926: text2=re.sub(r';([^\s])','; \g<1>',text)
927:
928: if field=="WEB_project_description":##Jedenfalls darf letzteres nicht gemacht werden, falls normaler text
929: text2=text
930:
931: #teste ob ergebnis leer und header dann nehme title
932:
933: if (text2=='') and (field=='WEB_project_header'):
934: return self.getContent('WEB_title')
935:
936: if filter:
937: splitted=text2.split("""<p class="picture">""")
938: if len(splitted)>1:
939: tmp=splitted[1].split("</p>")
940: #return repr(splitted[1])
941: try:
942: self.imageURL=tmp[0].split("\"")[1].encode('utf-8')
943: except:
944: try:
945: self.imageURL=tmp[0].split("src=")[1].split(" ")[0].encode('utf-8')
946: except:
947: self.imageURL=""
948:
949: split2="</p>".join(tmp[1:])
950:
951: text3=splitted[0]+split2
952:
953: splitted=text3.split("""<p class="picturetitle">""")
954: if len(splitted)>1:
955: tmp=splitted[1].split("</p>")
956: self.imagecap=tmp[0].encode('utf-8')
957:
958: split4="".join(tmp[1:])
959:
960: text5=splitted[0]+split4
961: else:
962: #keine caption
963: text5=text3
964: else:
965: #kein bild
966: text5=text2
967: else:
968: text5=text2
969:
970: #teste ob WEB_project_description und keine fuehrenden p tags
971: if (len(text5)>4) and (not text5[0:3]=='<p>') and (field=='WEB_project_description'):
972: text5= "<p>"+text5+"</p>"
973:
974:
975: #filter image
976:
977: text5=text5.lstrip().rstrip() #loescher leerzeichen und einzelndes br
978: if (text5=="<br>") or (text5=="<br/>"):
979: text5=""
980:
981: #logging.debug("getcontent: field=%s filter=%s -> %s"%(field,filter,repr(text5)))
982: return unicodify(text5)
983: #return utf8ify(text5) # return as utf-8 byte string
984:
985:
986: def showImagesOfPage(self,imageUrl=None):
987: """show Images of project"""
988: self.getContent('WEB_project_description',filter='yes') #get the content and store image infos into session
989: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','projectImageView.zpt')).__of__(self)
990: return pt()
991:
992:
993: def show_html(self):
994: """simple index"""
995: #return "HI"
996: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','MPIWGProject_index.zpt')).__of__(self)
997: return pt()
998:
999: def saveFromPreview(self):
1000: """save content aus preview"""
1001: self.WEB_project_description=self.previewTemplate.WEB_project_description[0:]
1002: self.REQUEST.RESPONSE.redirect("./index.html")
1003:
1004: def saveEditedContent(self,kupu=None,preview=None):
1005: """save Edited content"""
1006:
1007: if preview:
1008: kupu=preview
1009: #find content of body tags
1010: start=kupu.find("<body>")
1011: end=kupu.find("</body>")
1012: newcontent= kupu[start+6:end]
1013:
1014: if preview:
1015:
1016: return self.preview(newcontent)
1017:
1018: self.copyObjectToArchive()
1019: self.ZCacheable_invalidate()
1020: self.WEB_project_description=newcontent[0:]
1021:
1022: self.REQUEST.RESPONSE.redirect("./index.html")
1023:
1024: return True
1025:
1026: security.declareProtected('View management screens','edit')
1027: def edit(self,western=None):
1028: """Edit pages"""
1029: if western:
1030: self.REQUEST.RESPONSE.setCookie("MP_debug_code","western",path="/")
1031:
1032:
1033: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGProjectNeu.zpt')).__of__(self)
1034: return pt()
1035:
1036: edit_MPIWGProject_main = PageTemplateFile('zpt/edit_MPIWGProject_main', globals())
1037:
1038: def getPathStyle(self, path, selected, style=""):
1039: """returns a string with the given style + 'sel' if path == selected."""
1040:
1041: if path == selected:
1042: return style + 'sel'
1043: else:
1044: return style
1045:
1046: def getLabel(self):
1047: """returns label (or title) of this project"""
1048: l = self.getContent('xdata_07')
1049: if l:
1050: return l
1051: l = self.getContent('WEB_title')
1052: if l:
1053: return l
1054: return self.title
1055:
1056: def getBreadcrumbs(self):
1057: """return list of breadcrumbs from here to the root"""
1058: crumbs = []
1059: # skip direct parent Folder /projects/
1060: parent = self.aq_parent.aq_parent
1061: # get parents breadcrumbs
1062: if hasattr(parent, 'getBreadcrumbs'):
1063: crumbs = parent.getBreadcrumbs()
1064:
1065: # try to get acquisition URL from parent
1066: if hasattr(parent, 'absolute_url'):
1067: baseUrl = "%s/%s/"%(parent.absolute_url(), 'projects')
1068: else:
1069: baseUrl = "/en/research/projects/"
1070:
1071: # add in the internal project hierarchy
1072:
1073: ct=self.getContexts(parents=self.getContent('xdata_05'))
1074: # start with grandparents
1075: ct.reverse()
1076: for c in ct:
1077: label = shortenString(c[0].getLabel(), 13)
1078: crumbs.append((label, baseUrl+c[0].getId(), c[0]))
1079:
1080: # add this project
1081: crumbs.append((self.getLabel(), baseUrl+self.getId(), self))
1082:
1083: return crumbs
1084:
1085: def getRootProject(self):
1086: """returns the root (=top level) project of the current project"""
1087:
1088: ct=self.getContexts(parents=self.getContent('xdata_05'))
1089: if len(ct) > 0:
1090: return ct[-1][0]
1091: else:
1092: return self
1093:
1094:
1095: def preview(self,description):
1096: """preview"""
1097: tmpPro=getattr(self,"previewTemplate",None)
1098: if not tmpPro:
1099: tmpPro=MPIWGProject("previewTemplate")
1100: self._setObject("previewTemplate",tmpPro)
1101: for field in definedFields:
1102: setattr(tmpPro,field,getattr(self,field))
1103: tmpPro.WEB_project_description=description[0:]
1104: tmpPro.invisible=True
1105: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','previewFrame.zpt')).__of__(self)
1106: return pt()
1107:
1108: #return self.REQUEST.RESPONSE.redirect(self.REQUEST['URL1']+"/previewTemplate")
1109:
1110:
1111: def getWebProject_description(self):
1112: """get description"""
1113: debug= self.REQUEST.cookies.get("MP_debug_code",None)
1114:
1115: if debug and debug=="western":
1116: return """
1117: <html>
1118: <head>
1119: <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
1120: </head>
1121: <body>%s
1122: </html></body>
1123: """%self.WEB_project_description[0]
1124:
1125: return """
1126: <html>
1127: <head>
1128: <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
1129: </head>
1130: <body>%s
1131: </html></body>
1132: """%self.getContent('WEB_project_description')
1133:
1134:
1135:
1136: def editMPIWGProjectForm(self):
1137: """editform"""
1138: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGProject.zpt')).__of__(self)
1139: return pt()
1140:
1141: def isResponsibleScientist(self,key):
1142: """teste ob eine Person in der Liste der respl. scientists auftaucht"""
1143: #logging.info("XXXXXXXXXXXXX"+repr(self.responsibleScientistsList))
1144:
1145:
1146: keys = [unicodify(x[1]) for x in getattr(self,"responsibleScientistsList",[])]
1147: #logging.error("RESP. SCIEN:%s"%getattr(self,"responsibleScientistsList",[]))
1148: #logging.error("RESP. SCIEN:%s"%unicodify(key))
1149:
1150: if unicodify(key) in keys:
1151: return True
1152: else:
1153: return False
1154:
1155: def getPersonKeyList(self):
1156: """gibt die key Liste der beteiligten Personen zurueck (utf8 codiert)"""
1157: #logging.error("getPersonKeyList:%s"%getattr(self,'responsibleScientistsList',[]))
1158: try:
1159: return [utf8ify(x[1]) for x in getattr(self,'responsibleScientistsList',[])]
1160: except:
1161: return[]
1162:
1163:
1164: def myCapitalize(self,txt):
1165: """kapitalisiere auch Namen mit -"""
1166: splitted=[x.capitalize() for x in txt.split("-")]
1167: return "-".join(splitted)
1168:
1169: def getNamesOrdered(self,list):
1170: """Sortiert die Liste nach der Reihenfolge in xdata_01"""
1171:
1172: nameList=self.getContent('xdata_01')
1173: if nameList.find(";")>-1: # rate Trenner ist ;
1174: names=nameList.split(";")
1175: else:
1176: names=nameList.split(",")
1177:
1178: self._v_names=[]
1179: for name in names:
1180: self._v_names.append(name.rstrip().lstrip())
1181:
1182:
1183: def sort(x,y):
1184: try:
1185: return cmp(self._v_names.index(x[0]),self._v_names.index(y[0]))
1186: except:
1187: return 0
1188:
1189: list.sort(sort)
1190:
1191: return list
1192:
1193: ##nameList=nameList.replace(";",",") # falls ; als Trenner ersetze
1194:
1195:
1196:
1197:
1198: def identifyNames(self,nameList):
1199: """Bekommt eine Komma oder Semikolon getrennte Liste mit Name der Form Vorname MittelName(n) Nachname
1200: und ordnet diese dann Mitarbeiter IDs zu falls es schone eine Liste gibt wird im Projekte gibt wird diese Upgedated.
1201: @param nameList
1202: """
1203:
1204: if nameList.find(";")>-1: # rate Trenner ist ;
1205: names=nameList.split(";")
1206:
1207: else:
1208: names=nameList.split(",")
1209:
1210: ##nameList=nameList.replace(";",",") # falls ; als Trenner ersetze
1211: returnNamesDict={}
1212:
1213:
1214: for name in names:
1215: name=name.lstrip().rstrip()
1216: nameSplitted = name.split(" ")
1217: if len(nameSplitted)>1: #vor und nachname angegeben)
1218:
1219: lastname=nameSplitted[-1]
1220: firstname=nameSplitted[0]
1221: else:
1222: firstname =""
1223: lastname=nameSplitted[0]
1224:
1225: #finde Mitarbeiter mit den entsprechenden Name
1226:
1227: firstname=self.myCapitalize(firstname).encode('utf-8')
1228: lastname=self.myCapitalize(lastname).encode('utf-8')
1229: logging.info("Search: %s %s %s"%(name,repr(firstname),repr(lastname)))
1230: try:
1231: cataloggedNames=self.MembersCatalog(firstName=firstname,lastName=lastname)
1232: except:
1233: cataloggedNames=[]
1234: logging.error("ERROR: identifyNames %s %s"%sys.exc_info()[0:2])
1235:
1236: #Teste ob die ensprechenden Namen schon der Liste zu geordnet sind
1237: #if not hasattr(self,'responsibleScientistsList'):
1238: # self.responsibleScientistsList={}
1239: #
1240: # if name in self.responsibleScientistsList.values()
1241:
1242: if len(cataloggedNames)>0:
1243: returnNamesDict[name]=cataloggedNames
1244: else:
1245: returnNamesDict[name]=[]
1246:
1247: logging.error("id: %s"%repr(returnNamesDict))
1248: return returnNamesDict
1249:
1250: def editMPIWGProject(self,RESPONSE=None,fromEdit=None):
1251: """edit the project and archive the old version"""
1252:
1253: self.copyObjectToArchive() # archive the object
1254: self.ZCacheable_invalidate()
1255:
1256: for x in definedFields:
1257: if self.REQUEST.has_key(x):
1258:
1259: setattr(self,x,[self.REQUEST[x].decode('utf-8')])
1260:
1261:
1262:
1263:
1264: completedAt = self.REQUEST.get('completedAt')
1265: if not self.setCompletedAt(completedAt):
1266: RESPONSE.redirect('./editMPIWGBasisEditor?error="dateWrong')
1267:
1268: startedAt = self.REQUEST.get('startedAt')
1269: if not self.setStartedAt(startedAt):
1270: RESPONSE.redirect('./editMPIWGBasisEditor?error="dateWrong')
1271:
1272: if self.REQUEST.has_key('historicalNames'):
1273: self.en.changeHistoricalNames(self.getId(),self.REQUEST['historicalNames'].split("\n"))
1274:
1275: if self.REQUEST.has_key('active'):
1276: self.setActiveFlag(True)
1277: else:
1278: self.setActiveFlag(False)
1279:
1280: self.responsibleScientistsList=[] # setze die Liste der verantwortlichen Wissenschaftler zurueck
1281:
1282: names={}
1283: keys={}
1284: tmpList=[]
1285: for key in self.REQUEST.keys(): #gehe durch das Formular
1286: splitted=key.split("_")
1287: if splitted[0]=="responsibleScientist": #wenn es ein Feld der Form reponsibleScientist_nr_KEY gibt
1288: nr=splitted[2]
1289: if splitted[1]=="name":
1290: names[nr]=self.REQUEST[key]
1291: elif splitted[1]=="key":
1292: keys[nr]=self.REQUEST[key]
1293:
1294:
1295: for nr in names.keys():#schreibe keys und namen in die Liste, stelle ausserdem sicher, dass name unicode
1296: tmpList.append((unicodify(names[nr]),unicodify(keys.get(nr,""))))
1297:
1298: self.responsibleScientistsList=tmpList
1299: if fromEdit and (RESPONSE is not None):
1300: #RESPONSE.redirect('./editMPIWGBasisEditor')
1301: return self.editMPIWGBasisEditor(identifiedNames=self.identifyNames(self.decode(self.REQUEST.get('xdata_01',''))))
1302:
1303: else:
1304: if RESPONSE is not None:
1305: RESPONSE.redirect('manage_main')
1306:
1307:
1308:
1309: security.declareProtected('View managment screens','editMPIWGDisciplinesThemesEditor')
1310: def editMPIWGDisciplinesThemesEditor(self):
1311: """edit from edit"""
1312: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGDisciplinesThemesNeu.zpt')).__of__(self)
1313: return pt()
1314:
1315:
1316: def editMPIWGDisciplinesThemesForm(self):
1317: """edit the disciplines and themes Form"""
1318:
1319: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGDisciplinesThemes.zpt')).__of__(self)
1320: return pt()
1321:
1322: def editMPIWGDisciplinesThemes(self,disciplines=None,themes=None,RESPONSE=None,fromEdit=None):
1323: """edit disciplin and form"""
1324: if disciplines:
1325: if type(disciplines) is StringType:
1326: self.xdata_09=disciplines
1327: else:
1328: self.xdata_09=";".join(disciplines)
1329: else:
1330: self.xdata_09=""
1331: if themes:
1332: if type(themes) is StringType:
1333: self.xdata_10=themes
1334: else:
1335: self.xdata_10=";".join(themes)
1336: else:
1337: self.xdata_10=""
1338:
1339: if fromEdit and (RESPONSE is not None):
1340: self.redirect(RESPONSE,'./editMPIWGDisciplinesThemesEditor')
1341:
1342: else:
1343: if RESPONSE is not None:
1344: RESPONSE.redirect('manage_main')
1345:
1346:
1347: def isChecked(self,wert,list):
1348: """check if wert is in ; seperated list"""
1349:
1350: #felder sind manchmnal als liste mit einem element definiert
1351: if type(list) is StringType or UnicodeType:
1352: splitted=list.split(";")
1353: else:
1354: splitted=list[0].split(";")
1355:
1356: splitted=[y.rstrip().lstrip() for y in splitted]
1357:
1358: for x in splitted:
1359: x=re.sub(r"[^A-z ]","",x)
1360: if (not x==u'') and x in wert:
1361: return 1
1362: return 0
1363:
1364: security.declareProtected('View management screens','editMPIWGBasisEditor')
1365: def editMPIWGBasisEditor(self, identifiedNames=None):
1366:
1367: """editform"""
1368: if not identifiedNames:
1369: identifiedNames=self.identifyNames(self.getContent('xdata_01'))
1370: # identifiedNames=self.getFullNameEntries()
1371:
1372: logging.error("IdentifiedNames: %s"% repr(identifiedNames))
1373: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGBasisNeu.zpt')).__of__(self)
1374: return pt(identifiedNames=identifiedNames)
1375:
1376: security.declareProtected('View management screens','editMPIWGBasisForm')
1377: def editMPIWGBasisForm(self):
1378: """editform"""
1379: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGBasis.zpt')).__of__(self)
1380: return pt()
1381:
1382: security.declareProtected('View management screens','editMPIWGRelatedPublicationsForm')
1383: def editMPIWGRelatedPublicationsForm(self):
1384: """Edit related Publications"""
1385: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGRelatedPublications.zpt')).__of__(self)
1386: return pt()
1387:
1388:
1389: def loadNewFileForm(self):
1390: """Neues XML-File einlesen"""
1391: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','MPIWGProject_newfile.zpt')).__of__(self)
1392: return pt()
1393:
1394: def loadNewFile(self,RESPONSE=None):
1395: """einlesen des neuen files"""
1396: fileupload=self.REQUEST['fileupload']
1397: if fileupload:
1398: file_name=fileupload.filename
1399: filedata=fileupload.read()
1400:
1401: argv=xmlhelper.proj2hash(filedata)
1402: #print argv.keys()
1403: for arg in definedFields:
1404:
1405: #print arg,argv[arg],getattr(self,arg)
1406: try:
1407: temp=argv[arg][0:]
1408: #old=getattr(self,arg)
1409: setattr(self,arg,temp)
1410: #print old,getattr(self,arg)
1411: except:
1412: """nothing"""
1413:
1414: if RESPONSE is not None:
1415: RESPONSE.redirect('manage_main')
1416:
1417: def manage_addMPIWGProjectForm(self):
1418: """form for adding the project"""
1419: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMPIWGProjectForm.zpt')).__of__(self)
1420: return pt()
1421:
1422: def manage_addMPIWGProject(self,id,RESPONSE=None):
1423: """method to add a project"""
1424: #print argv
1425: fileupload=self.REQUEST.get('fileupload',None)
1426: if fileupload:
1427:
1428: file_name=fileupload.filename
1429: filedata=fileupload.read()
1430:
1431: argv=xmlhelper.proj2hash(filedata)
1432:
1433: #print argv
1434: newObj=MPIWGProject(id,argv)
1435: else:
1436: newObj=MPIWGProject(id)
1437:
1438: self._setObject(id,newObj)
1439:
1440:
1441: if RESPONSE is not None:
1442: RESPONSE.redirect('manage_main')
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>