Mercurial > hg > MPIWGWeb
view MPIWGProjects.py @ 161:2b5adc7f5445
english and german footer
author | casties |
---|---|
date | Thu, 06 Jun 2013 19:11:45 +0200 |
parents | a9ad7dd7a8b2 |
children | 47392bf3fcba |
line wrap: on
line source
"""This contains the class MPIWG Projects for organizing and maintaining the different project pages $author dwinter 26.06.2008 """ from Products.PageTemplates.PageTemplateFile import PageTemplateFile from OFS.Image import Image from App.ImageFile import ImageFile from OFS.SimpleItem import SimpleItem from OFS.Folder import Folder from AccessControl import ClassSecurityInfo from Globals import package_home import urllib import re import os import sys import logging import time import unicodedata import xml.etree.ElementTree as ET from SrvTxtUtils import getInt, unicodify, utf8ify, serialize, refreshingImageFileIndexHtml, shortenString from Products.ZDBInterface.ZDBInterfaceFolder import ZDBInterfaceFolder import xmlhelper # Methoden zur Verwaltung der projekt xml from HashTree import HashTree import MPIWGHelper # TODO: better names for the fields fieldLabels = {'WEB_title':'WEB_Title', 'xdata_01':'Responsible Scientists', 'xdata_02':'Department', 'xdata_03':'Historical Persons', 'xdata_04':'Time period', 'xdata_05':'Sorting number', 'xdata_06':'Keywords', 'xdata_07':'Short title', 'xdata_08':'Other involved scholars' , 'xdata_09':'Disciplines', 'xdata_10':'Themes', 'xdata_11':'Object Digitallibrary', 'xdata_12':'Cooperation partners', 'xdata_13':'Funding institutions', 'WEB_project_header':'WEB_project_header', 'WEB_project_description':'WEB_project_description', 'WEB_related_pub':'WEB_related_pub'} definedFields = fieldLabels.keys() # TODO: should this be sorted? editableFields = ('xdata_07', 'xdata_01', 'xdata_05', 'xdata_08', 'xdata_12', 'xdata_13') # die folgenden Klassen sind jetzt in einzelne Files ausgelagert aus Kompatibilitaetsgruenden, bleiben die Klassen hier noch drin. # Sonst funktionieren die alten Webseiten nicht mehr. import MPIWGRoot import MPIWGLink import MPIWGTemplate class MPIWGRoot(MPIWGRoot.MPIWGRoot): """depricated""" class MPIWGLink(MPIWGLink.MPIWGLink): """depricated""" class MPIWGTemplate(MPIWGTemplate.MPIWGTemplate): """depricated""" class MPIWGProject_publication(Folder): """publications object fuer project""" meta_type = "MPIWGProject_publication" text = None link = None bookId = None # templates edit = PageTemplateFile('zpt/project/related_publication/edit_basic', globals()) redirect = MPIWGHelper.redirect def hasLinkToBookPage(self): """teste ob eingebener link zu einer MPIWG Book page geht""" logging.debug("MPIWGProject_publication - begin hasLinkToBookPage") if not self.link: return False # es gibt keinen link paths = self.link.split('/') if len(paths) > 2: # book page should be in folder books bookid = None try: idx = paths.index('books') bookid = paths[idx + 1] book = self.en.books[bookid] self.bookId = bookid return True except: logging.debug("hasLinkToBookPage: not a book page link=%s"%self.link) self.bookId = None return False def getBookId(self): """Return the book page id.""" return self.bookId getUrl = MPIWGHelper.getUrl def editPublication(self, text=None, description=None, link=None, RESPONSE=None): """edit a publication""" if (not text) and (not description): pt = self.edit return pt() if text: self.text = text if description: self.description = description if link: self.link = link self.hasLinkToBookPage() if RESPONSE: self.redirect(RESPONSE, "../managePublications") class MPIWGProject_relatedProject(SimpleItem): """publications object fuer project""" meta_type = "MPIWGProject_relatedProject" objid = None projectLabel = None # templates edit = PageTemplateFile('zpt/project/related_project/edit_basic', globals()) redirect = MPIWGHelper.redirect def getProjectId(self): """Return the related project id.""" return self.objid def getProject(self): """Return the related project object.""" return getattr(self.projects, self.objid, None) def getProjectTitle(self): """Return the title of the related project.""" return getattr(self, 'projectWEB_title', None) def getProjectLabel(self): """Return the label of the related project.""" label = getattr(self, 'projectLabel', None) if not label: proj = self.getProject() if proj is not None: label = proj.getLabel() self.projectLabel = label return label getUrl = MPIWGHelper.getUrl def editRelatedProject(self, link=None, RESPONSE=None): """edit a publication""" if (not link): pt = self.editDescription return pt() # hole die id des projektes splitted = link.split("/") # teste ob es das project gibt if len(splitted) < 1: self.redirect(RESPONSE, 'errorRelatedProjects?link=' + link) objid = splitted[-1] object = getattr(self.projects, objid, None) if object is None: self.redirect(RESPONSE, 'errorRelatedProjects?link=' + link) self.orginallink = link[0:] self.objid = objid[0:] self.projectWEB_title = object.getProjectTitle() self.projectLabel = object.getLabel() self.enabled = True; if RESPONSE: self.redirect(RESPONSE, "../manageRelatedProjects") class MPIWGProject_image(Image): """Images for Projects""" meta_type = "MPIWGProject_image" # templates oldShowImage = PageTemplateFile('zpt/project/image/projectImageView', globals()) editForm = PageTemplateFile('zpt/project/image/edit_basic', globals()) getUrl = MPIWGHelper.getUrl def getCaption(self): """Return the image caption.""" return getattr(self, 'caption', None) def getLink(self): """Return the image link.""" return getattr(self, 'link', None) def editImage(self, file=None, caption=None, link=None, RESPONSE=None): """edit the Image""" if (not file) and (not caption): pt = self.editForm return pt() if file and (not file.filename.strip() == ""): self.manage_upload(file) if caption: if isinstance(caption, list): caption = caption[0] self.caption = caption if link: self.link = link if RESPONSE: self.redirect(RESPONSE, "../manageImages") class MPIWGProject_InfoBlock(SimpleItem): """publications object fuer project""" meta_type = "MPIWGProject_InfoBlock" # templates edit = PageTemplateFile('zpt/project/infoblock/edit_items', globals()) redirect = MPIWGHelper.redirect def __init__(self, id, title=None): """Create info block.""" self.id = id self.title = title self.place = 0 self.items = [] def getTitle(self): """Return the title.""" return self.title def getItems(self): """Return the list of items.""" return self.items def setItems(self, items): """Set the list of items.""" self.items = items self._p_changed = True def addItem(self, item=None, text=None, link=None, RESPONSE=None): """Add an item to the InfoBox""" if item is None: item = {'text': text, 'link': link} self.items.append(item) self._p_changed = True if RESPONSE is not None: self.redirect(RESPONSE, 'edit') def deleteItem(self, idx, RESPONSE=None): """Delete an item from the info block.""" try: del self.items[int(idx)] self._p_changed = True except: logging.error("InfoBlock deleteItem: error deleting item %s!"%idx) if RESPONSE is not None: self.redirect(RESPONSE, 'edit') def moveItem(self, idx, op, RESPONSE=None): """Move items up or down the list.""" try: idx = int(idx) if op == 'up': if idx > 0: self.items[idx-1], self.items[idx] = self.items[idx], self.items[idx-1] elif op == 'down': if idx < len(self.items)-1: self.items[idx], self.items[idx+1] = self.items[idx+1], self.items[idx] self._p_changed = True except: logging.error("InfoBlock moveItem: error moving item at %s!"%idx) if RESPONSE is not None: self.redirect(RESPONSE, 'edit') def editItems(self, REQUEST, RESPONSE=None): """Change items from request form.""" form = REQUEST.form for k in form: t, n = k.split('_') if t in ['text', 'link']: try: logging.debug("editItems: change[%s].%s = %s"%(n,t,repr(form[k]))) self.items[int(n)][t] = form[k] except: logging.error("InfoBlock editItems: error changing item %s!"%k) self._p_changed = True if RESPONSE is not None: self.redirect(RESPONSE, 'edit') class MPIWGProject(Folder): """Class for Projects""" security = ClassSecurityInfo() meta_type = 'MPIWGProject' manage_options = Folder.manage_options + ( {'label':'Load New File', 'action':'loadNewFileForm'}, {'label':'Edit', 'action':'editDescription'}, ) # {'label':'Edit ProjectInfo','action':'editMPIWGProjectForm'}, # {'label':'Edit BasisInfo','action':'editMPIWGBasisForm'}, # {'label':'Edit Publications','action':'editMPIWGRelatedPublicationsForm'}, # {'label':'Edit Themes & Disciplines','action':'editMPIWGDisciplinesThemesForm'}, # {'label':'Versionmanager','action':'versionManageForm'}, # # templates # project_html = PageTemplateFile('zpt/project/project_index_html', globals()) # edit templates edit_css = ImageFile('css/edit.css', globals()) # make css refreshable for development edit_css.index_html = refreshingImageFileIndexHtml # user-accessible editing templates edit_template = PageTemplateFile('zpt/project/edit_template', globals()) security.declareProtected('View management screens', 'editBasic') editBasic = PageTemplateFile('zpt/project/edit_basic', globals()) security.declareProtected('View management screens', 'editDescription') editDescription = PageTemplateFile('zpt/project/edit_description', globals()) security.declareProtected('View management screens', 'editRelatedProjectsForm') editRelatedProjectsForm = PageTemplateFile('zpt/project/edit_related_projects', globals()) editRelatedProjectsError = PageTemplateFile('zpt/project/edit_related_projects_error', globals()) security.declareProtected('View management screens', 'editImagesForm') editImagesForm = PageTemplateFile('zpt/project/edit_images', globals()) security.declareProtected('View management screens', 'editPublicationsForm') editPublicationsForm = PageTemplateFile('zpt/project/edit_publications', globals()) security.declareProtected('View management screens', 'editInfoBlocksForm') editInfoBlocksForm = PageTemplateFile('zpt/project/edit_infoblocks', globals()) security.declareProtected('View management screens', 'editAdditionalPublicationsForm') editAdditionalPublicationsForm = PageTemplateFile('zpt/project/pubman/change_publications', globals()) security.declareProtected('View management screens', 'editAddAdditionalPublications') editAddAdditionalPublications = PageTemplateFile('zpt/project/pubman/add_publications', globals()) security.declareProtected('View management screens', 'edit') edit = editDescription # management templates security.declareProtected('View management screens', 'loadNewFileForm') loadNewFileForm = PageTemplateFile('zpt/project/manage_newfile', globals()) description_only_html = PageTemplateFile('zpt/project/description_only_html', globals()) # additional pages additional_publications_html = PageTemplateFile('zpt/project/pubman/show_publications', globals()) def __init__(self, id, argv=None): """initiere classe""" self.creationTime = time.strftime("%Y%m%d%H%M%S", time.localtime())[0:] self.id = id self.title = id self.isActiveFlag = True # Flag is true is the project is still active, False if accomplished self.responsibleScientistsList = [] # enthaelt die Lister der verantwortlichen Wissenschaftler in der Form (NAME, KEY), key ist "" flass Wissenschaftler nicht an unserem Haus self.projectThumb = None if argv: for arg in definedFields: try: setattr(self, arg, argv[arg]) except: setattr(self, arg, "") else: for arg in definedFields: setattr(self, arg, '') def index_html(self): """default html representation""" # TODO: do we need to do date-stuff? # get template pt = self.project_html # render template return pt() redirect = MPIWGHelper.redirect def getDefinedFields(self): """show all defined fields.""" return definedFields def getFieldLabels(self): """Return the field labels dict.""" return fieldLabels def getEditableFields(self): """giveListofDatafields""" return editableFields def getNumber(self): """returns sorting number""" n = getattr(self, 'xdata_05', None) if isinstance(n, list): # compat with old lists return n[0] else: return n def getProjectTitle(self, forSorting=False): """returns the project title""" t = getattr(self, 'WEB_title', None) if isinstance(t, list): # compat with old lists t = t[0] if forSorting and t is not None: # remove stopwords and signs for sorting if t.lower().startswith('a '): t = t[2:] elif isinstance(t, unicode) and unicodedata.category(t[0])[0] != 'L': t = t[1:] return t def getLabel(self): """returns label (or title) of this project""" l = getattr(self, 'xdata_07', None) if isinstance(l, list): # compat with old lists l = l[0] if l: return l else: return self.getProjectTitle() def getResponsibleScientists(self): """returns the responsible scientists as string""" t = getattr(self, 'xdata_01', None) if isinstance(t, list): # compat with old lists return t[0] else: return t def getResponsibleScientistsList(self): """returns a list with the responsible scientists as dicts with name, key, and shortname""" return getattr(self, 'responsibleScientistsList', []) def setResponsibleScientistsList(self, nameDict): """sets the responsibleScientistsList from nameDict. List will be ordered like the responsible scientists field.""" names = self.getResponsibleScientists() if names.find(";") > -1: # rate Trenner ist ; nameList = names.split(";") else: nameList = names.split(",") scientistsList = [] for name in nameList: name = unicodify(name.strip()) if not name: continue logging.debug("setResponsibleScientistsList: name=%s"%repr(name)) if name in nameDict: # found in data data = nameDict[name] scientistsList.append({'name': name, 'key': data['key'], 'username': data['username']}) else: scientistsList.append({'name': name}) logging.debug("setResponsibleScientistsList: nameDict=%s new list=%s"%(repr(nameDict),repr(scientistsList))) self.responsibleScientistsList = scientistsList # force update of the Properties list in the ZopeDB self._p_changed = 1 def getInvolvedScholars(self): """returns the other involved scholars""" t = getattr(self, 'xdata_08', None) if isinstance(t, list): # compat with old lists return t[0] else: return t def getCooperationPartners(self): """returns the cooperation partners""" t = getattr(self, 'xdata_12', None) if isinstance(t, list): # compat with old lists return t[0] else: return t def getMPIWGProject(self): """Return this project for acquisition.""" return self def getMPIWGProjectUrl(self): """Return this project for acquisition.""" return self.absolute_url() getUrl = MPIWGHelper.getUrl def getThumbUrl(self, default=None): """returns the URL of the project thumbnail image""" thumb = getattr(self, 'projectThumb', None) if thumb is None: # get thumb from list (thumb is last image) imgs = self.getImageList() if len(imgs) > 0: thumb = imgs[-1] self.projectThumb = thumb if thumb is None: return default return thumb.absolute_url() def getDepartment(self): """returns the department of this project""" num = self.getNumber() pp = num.find('.') if pp > 0: num = num[:pp] return self.en.getMPIWGRoot().getDepartment(projectNumber=num) def getDepartmentId(self): """returns the id of the department of this project""" dep = self.getDepartment() if dep is not None: return dep.getId() return None def getDescription(self, filter=None, length=0): """returns the project description""" text = getattr(self, 'WEB_project_description', None) if isinstance(text, list): # compat with old lists text = text[0] if filter == 'plaintext': # filter out any tags, keep only text try: xmltext = utf8ify("<div>%s</div>"%text) dom = ET.fromstring(xmltext) plaintext = "" for elem in dom.iter(): if elem.tag == 'style': # ignore tag continue if elem.text: plaintext += elem.text if elem.tail: plaintext += elem.tail if length > 0 and len(plaintext) > length: break text = plaintext except Exception, e: logging.warn("getDesciption: error parsing description! Returning everything. %s"%e) if length > 0 and len(text) > length: # try to not break words if text[length] not in [' ', '.', '?', '!']: # search the last blank length = text.rfind(' ', 0, length) return text[:length] + '...' return text def getSuperProjects(self): """returns a list of ancestor projects to the root""" tree = self.getProjectTree() return tree.getAncestorsOf(self.getNumber()) def getSubProjects(self, active=1): """returns a list of child projects""" tree = self.getProjectTree() return [p for p in tree.getChildrenOf(self.getNumber()) if p.checkActive(active)] def getRelatedDigitalSources(self): """returns the related digital sources""" t = getattr(self, 'xdata_11', None) if isinstance(t, list): # compat with old lists return t[0] else: return t def getFundingInstitutions(self): """returns the funding institutions""" t = getattr(self, 'xdata_13', None) if isinstance(t, list): # compat with old lists return t[0] else: return t def _moveObjectPlace(self, objectList, objectId, direction): """Move object with objectId from objectList in direction by changing its place attribute.""" if not objectId or not direction: return for idx in range(len(objectList)): object = objectList[idx] if object.getId() == objectId: if direction == 'up': if idx > 0: # move up objectList[idx -1].place += 1 objectList[idx].place -= 1 elif direction == 'down': if idx < len(objectList) - 1: # move down objectList[idx + 1].place -= 1 objectList[idx].place += 1 return def getImageList(self): """returns the sorted list of images for this project""" items = self.objectValues(spec='MPIWGProject_image') # sort by place return sorted(items, key=lambda x:int(getattr(x, 'place', 0))) def scaleImage(self,REQUEST=None,RESPONSE=None): """scale the last image""" from PIL import Image; from cStringIO import StringIO; import ImageFilter images = self.getImageList(); if len(images)>0: img = images[-1] #nimmt das letze logging.debug(img) datStringIO = StringIO(); """ data=img.data if isinstance(data, str): datStringIO.write(data) else: while data is not None: datStringIO.write(data.data) data=data.next """ logging.debug(img.absolute_url()) url = img.absolute_url() if not url.startswith("http"): url=REQUEST['URL0']+url ul = urllib.urlopen(url) datStringIO = StringIO(ul.read()); try: pilImg = Image.open(datStringIO) except: logging.error("scale image input:"+self.getId()) return w,h = pilImg.size logging.debug("oldsize: %s %s"%(w,h)) targetW=120. targetH=75. if targetW == w and targetH == h: return facW=targetW/w h1 = int(h*facW) if h1<targetH: #bild zu klein in h facH=targetH/h w1=int(w*facH) fs = min(max(int(1/facH)+1,3),10) logging.debug(fs) if (1/facH) > 2: pilImg = pilImg.filter(ImageFilter.BLUR) try: pilImg = pilImg.filter(ImageFilter.MaxFilter(fs)) except: pilImg = pilImg.filter(ImageFilter.MaxFilter(fs-1)) logging.debug("Xnew size: %s %s"%(w1,targetH)) res = pilImg.resize((w1,int(targetH)),Image.ANTIALIAS); else: fs = min(max(int(1/facW)+1,3),10) logging.debug(fs) if (1/facW) > 2: try: pilImg = pilImg.filter(ImageFilter.BLUR) except: pass #some image types cannot be filter, just ignore try: pilImg = pilImg.filter(ImageFilter.MaxFilter(fs)) except: try: pilImg = pilImg.filter(ImageFilter.MaxFilter(fs-1)) except: pass logging.debug("ynew size: %s %s"%(targetW,h1)) res = pilImg.resize((int(targetW),h1)) nw,nh = res.size cutW1=int(nw/2-(targetW/2)) cutW2=int(nw/2+(targetW/2)) cutH1=int(nh/2-(targetH/2)) cutH2=int(nh/2+(targetH/2)) res2 = res.crop((cutW1,cutH1,cutW2,cutH2)) outS = StringIO() #res2.save("/tmp/"+self.getId()+".jpg") try: res2.save(outS,"JPEG") self.addImage(outS, None, RESPONSE, filename="thumb.jpg") except: logging.error("scale image:"+self.getId()) def addImage(self, fileHd, caption, RESPONSE=None, filename=None): """add an MPIWG_Project_image""" if not filename: filename = fileHd.filename if not fileHd: fileHd = file(os.path.join(package_home(globals()), 'blank.gif')) newImage = MPIWGProject_image(filename, filename, fileHd) self._setObject(filename, newImage) obj = getattr(self, filename) if caption is None: obj.caption=None else: obj.caption = caption[:] obj.enabled = True; obj.place = self._getLastImageNumber() + 1 obj.id = filename # invalidate thumbnail self.projectThumb = None if RESPONSE is not None: self.redirect(RESPONSE, 'manageImages') def _getLastImageNumber(self): items = self.getImageList() if not items: return 0 else: return getattr(items[-1], 'place', 0) def manageImages(self, name=None, op=None): """manage images""" self._moveObjectPlace(self.getImageList(), name, op) # invalidate thumbnail self.projectThumb = None pt = self.editImagesForm return pt() def deleteImage(self, id, RESPONSE=None): """delete Image id""" try: self.manage_delObjects([id]) except: logging.error("ERROR MPIWG: %s %s" % sys.exc_info()[0:2]) # invalidate thumbnail self.projectThumb = None if RESPONSE: self.redirect(RESPONSE, 'manageImages') def getPublicationList(self): """returns the list of related publications""" items = self.objectValues(spec='MPIWGProject_publication') # sort by place items.sort(key=lambda x:int(getattr(x, 'place', 0))) return items def addPublication(self, text=None, link=None, RESPONSE=None): """add an MPIWG_Publication""" if text or link: number = self._getLastPublicationNumber() + 1 name = "publication_" + str(number) while hasattr(self, name): number += 1 name = "publication_" + str(number) newPublication = MPIWGProject_publication(name) self._setObject(name, newPublication) obj = getattr(self, name) obj.text = text obj.link = link obj.enabled = True; obj.place = self._getLastPublicationNumber() + 1 obj.id = name # hasLinkToBookPage updates bookid if available if obj.hasLinkToBookPage() and not text: # take title from book page try: book = self.en.books[obj.bookId] obj.text = book.getInfo('title') except: pass if RESPONSE is not None: self.redirect(RESPONSE, 'managePublications') def _getLastPublicationNumber(self): items = self.getPublicationList() if not items: return 0 else: return getattr(items[-1], 'place', 0) def managePublications(self, name=None, op=None): """manage publications""" self._moveObjectPlace(self.getPublicationList(), name, op) pt = self.editPublicationsForm return pt() def deletePublication(self, id, RESPONSE=None): """delete Publication id""" self.manage_delObjects([id]) if RESPONSE: self.redirect(RESPONSE, 'managePublications') def getRelatedProjectList(self): """returns the list of related projects""" items = self.objectValues(spec='MPIWGProject_relatedProject') # sort by place items.sort(key=lambda x:int(getattr(x, 'place', 0))) return items def addRelatedProject(self, link, RESPONSE=None): """add a MPIWGProject_relatedProject""" number = self._getLastRelatedProjectNumber() + 1 name = "related_project_" + str(number) while hasattr(self, name): number += 1 name = "related_project_" + str(number) # hole die id des projektes splitted = link.split("/") # teste ob es das project gibt if len(splitted) < 1: self.redirect(RESPONSE, 'errorRelatedProjects?link=' + link) objid = splitted[-1] object = getattr(self.projects, objid, None) if object == None: self.redirect(RESPONSE, 'errorRelatedProjects?link=' + link) return newPublication = MPIWGProject_relatedProject(name) self._setObject(name, newPublication) obj = getattr(self, name) obj.orginallink = link[0:] obj.objid = objid[0:] logging.debug("add relobj:objid" + repr(obj.objid)) obj.projectWEB_title = object.getProjectTitle() logging.debug("add relobj:webtitle" + repr(obj.projectWEB_title)) obj.enabled = True; obj.place = self._getLastRelatedProjectNumber() + 1 obj.id = name if RESPONSE is not None: self.redirect(RESPONSE, 'manageRelatedProjects') def _getLastRelatedProjectNumber(self): items = self.getRelatedProjectList() if not items: return 0 else: return getattr(items[-1], 'place', 0) def manageRelatedProjects(self, name=None, op=None): """manage related projects""" self._moveObjectPlace(self.getRelatedProjectList(), name, op) pt = self.editRelatedProjectsForm return pt() def deleteRelatedProject(self, id, RESPONSE=None): """delete Publication id""" self.manage_delObjects([id]) if RESPONSE: self.redirect(RESPONSE, 'manageRelatedProjects') def errorRelatedProjects(self, link): """error creating a related project""" pt = self.editRelatedProjectsError return pt(link=link) def getInfoBlockList(self): """returns the list of related projects""" items = self.objectValues(spec='MPIWGProject_InfoBlock') # sort by place items.sort(key=lambda x:int(getattr(x, 'place', 0))) return items def addInfoBlock(self, block_title=None, item_text=None, item_link=None, RESPONSE=None): """add a MPIWGProject_InfoBlock""" if block_title: number = self._getLastInfoBlockNumber() + 1 name = "infoblock_" + str(number) while hasattr(self, name): number += 1 name = "infoblock_" + str(number) newBlock = MPIWGProject_InfoBlock(name, block_title) # add block to project self._setObject(name, newBlock) obj = getattr(self, name) obj.place = self._getLastInfoBlockNumber() + 1 if item_text: obj.addItem(text=item_text, link=item_link) if RESPONSE is not None: self.redirect(RESPONSE, 'manageInfoBlocks') def _getLastInfoBlockNumber(self): items = self.getInfoBlockList() if not items: return 0 else: return getattr(items[-1], 'place', 0) def manageInfoBlocks(self, name=None, op=None): """manage related projects""" self._moveObjectPlace(self.getInfoBlockList(), name, op) pt = self.editInfoBlocksForm return pt() def deleteInfoBlock(self, id, RESPONSE=None): """delete Publication id""" self.manage_delObjects([id]) if RESPONSE: self.redirect(RESPONSE, 'manageInfoBlocks') def getAdditionalPublicationList(self): """hole publications aus der datenbank""" query="select * from pubmanbiblio_projects where lower(key_main) = lower(%s) order by priority DESC" return self.executeZSQL(query,[self.getId()]) def hasAdditionalPublications(self): """test if extended publication list exists""" query="select count(*) from pubmanbiblio_projects where lower(key_main) = lower(%s)" res= self.executeZSQL(query,[self.getId()]) if res[0].count > 0: return True else: return False def addAdditionalPublicationsFromPubman(self,REQUEST): """addPublications from pubman""" data=REQUEST.form if data.get("method",None) is None: pt = self.editAddAdditionalPublications return pt() if data.get("method") == "search": entries= self.mpiwgPubman.search(data) pt = self.editAddAdditionalPublications return pt(values=entries) if data.get("method") == "add": return self.addEntriesToAdditionalPublicationList(data) #pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt/staff/pubman','add_publications.zpt')).__of__(self) def addEntriesToAdditionalPublicationList(self,data): """fuege eintrage aus data zur publications liste. @param data Map mit escidocID --> value value muss "add" sein damit hinzugefuegt wird""" for key in data.keys(): if key.startswith('escidoc:'): query="INSERT INTO pubmanbiblio_projects (key_main,escidocId) values (%s,%s)" if data.get(key)=="add": self.executeZSQL(query,[self.getId(),key]) if hasattr(self,'REQUEST'): return self.REQUEST.response.redirect("changeAdditionalPublications") def changeAdditionalPublications(self,REQUEST): """change published publications""" data=REQUEST.form if data.get("method","change"): for key in data.keys(): splitted=key.split("__") #format escidoc_id__p fuer priority, nur escidocid value=data[key] if len(splitted)==1: self.deleteFromAdditionalPublicationList(key); elif(splitted[1]) == "p": self.setAdditionalPublicationPriority(splitted[0],value); pt = self.editAdditionalPublicationsForm return pt() def deleteFromAdditionalPublicationList(self,escidocid): """Loessche publication with escidoc id from publication list""" query ="DELETE FROM pubmanbiblio_projects WHERE escidocid=%s and key_main=%s" self.executeZSQL(query,[escidocid,self.getId()]); def setAdditionalPublicationPriority(self,escidocid,value): query="update pubmanbiblio_projects set priority=%s where escidocid=%s and key_main=%s" try: value = int(value) self.executeZSQL(query,[value,escidocid,self.getId()]); except: logging.error("couldn't change:") logging.error(escidocid) logging.error(value) def getActualVersion(self, date=None): """actuelle version""" def sortProjectsByTime(x, y): return cmp(x[1].archiveTime, y[1].archiveTime) if not date: if self.isCurrentVersion(): return self else: return None # suche ob aeltere versionen vorhanden sind finds = self.ZopeFind(self, obj_metatypes=['MPIWGProject']) if not finds: # wenn nicht dann teste ob die aktuelle version schon existiert hat. ad = getattr(self, 'creationTime', '20050101000000') if int(date) > int(ad): return self else: return None else: finds.sort(sortProjectsByTime) for find in finds: # gehe durch die alten Projekte und finde das entprechende if (int(find[1].archiveTime) > int(date)) and (int(date) > int(getattr(find[1], 'creationTime', '20050101000000'))): return find[1] # kein passendes gefunden, dann teste ob das aktuelle in frage kommt ad = getattr(self, 'creationTime', '20050101000000') if int(date) > int(ad): return self else: return None def isCurrentVersion(self): """Return if project is the current version.""" currentTime = time.localtime() # print getattr(self,'archiveTime',currentTime) return (getattr(self, 'archiveTime', currentTime) >= currentTime) def copyObjectToArchive(self): """kopiere aktuelles objekt ins archiv""" logging.info("copytoarchive 1") cb = self.aq_parent.manage_copyObjects(self.getId()) logging.info("copytoarchive 2") self.manage_pasteObjects(cb) logging.info("copytoarchive 3") actualTime = time.localtime() self.manage_renameObject(self.getId(), self.getId() + "_" + time.strftime("%Y%m%d%H%M%S", actualTime)) logging.info("copytoarchive 4") obj = getattr(self, self.getId() + "_" + time.strftime("%Y%m%d%H%M%S", actualTime)) obj.setArchiveTime(time.strftime("%Y%m%d%H%M%S", actualTime)) logging.info("copytoarchive 5") ids = [x[0] for x in self.ZopeFind(obj, obj_metatypes=['MPIWGProject'])] logging.info("copytoarchive 6") obj.manage_delObjects(ids) logging.info("copytoarchive 7") def setArchiveTime(self, time): """set Archive Time""" self.archiveTime = time[0:] def delArchiveTime(self): """delete archive time""" del self.archiveTime def isActiveProject(self): """check if the project is still active, default is true.""" return getattr(self, 'isActiveFlag', True) def checkActive(self, active): """returns if the project state matches the active state. active = 0 : all projects active = 1 : active projects active = 2 : inactive projects """ act = getattr(self, 'isActiveFlag', True) return (active == 1 and act) or (active == 0) or (active == 2 and not act) def isArchivedProject(self): """check if the project is archived""" completed = getattr(self, 'completedAt', '') # completed leer if completed == "" : return False; if completed == 0: return False; return True def checkArchived(self, archived): """returns if the project state matches the archived state. archived = 0 : all projects archived = 1 : current projects archived = 2 : archived projects """ arch = self.isArchivedProject() return (archived == 1 and not arch) or (archived == 0) or (archived == 2 and arch) def setActiveFlag(self, status=True): """set the active flag""" self.isActiveFlag = status def setCompletedAt(self, date): """set the date of completion, date should be in the form DD.MM.YYYY or MM.YYYY or YYYY""" # logging.info("DATE:"+repr(date)) transformedDate = self.transformDate(date); # logging.info("transformed"+repr(transformedDate)) if transformedDate is not None: setattr(self, "completedAt", transformedDate) return True; else: return False; def setStartedAt(self, date): """set the date of start, date should be in the form DD.MM.YYYY or MM.YYYY or YYYY""" # logging.info("DATE:"+repr(date)) transformedDate = self.transformDate(date); # logging.info("transformed"+repr(transformedDate)) if transformedDate is not None: setattr(self, "startedAt", transformedDate) return True; else: return False; def getCompletedAt(self): """gibt das transformierte Datum zurueck, an dem das Projekt beendet wurde.""" date = getattr(self, 'completedAt', '') if date: return self.reTransformDate(date); else: return "" def getStartedAt(self): """gibt das transformierte Datum zurueck, an dem Projekt begonnen wurde.""" date = getattr(self, 'startedAt', '') if date: return self.reTransformDate(date); else: return ''; def reTransformDate(self, date): """transformiert , transformdate zurueck""" year = int(date / 10000) month = int((date - year * 10000) / 100) day = int((date - year * 10000 - month * 100)) if (day == 0) and (month == 0): return """%s""" % year; if day == 0 : return """%s.%s""" % (month, year); return """%s.%s.%s""" % (day, month, year); def transformDate(self, date): """transformiert ein Datum von DD.MM.YYYY, MM.YYYY,YYYY nach YYYYMMDD, alle nicht angebenen Werte werden auf 0 gesetzt, es wird null zurueckgegeben falls das Datum ungueltig ist""" if (date == None): return None; if (date.lstrip().rstrip() == "") : return ""; splitted = date.split(".") length = len(splitted) year = 0 month = 0 day = 0 if length > 3: return ""; if length == 3: day = int(splitted[0]) if length > 1: month = int(splitted[length - 2]) if length > 0: try: year = int(splitted[length - 1]) except: pass # # logging.info("month:"+(month)) if not (0 <= month < 13): return None; if not(0 <= day < 32): return None; if (year > 0) and (year < 1900): # jahr nicht vierstellig eingegeben year = 2000 + year; return year * 10000 + month * 100 + day def checkDate(self, date): """teste ob zum Zeitpunkt date eine andere version existierte""" def sortProjectsByTime(x, y): return cmp(x[1].archiveTime, y[1].archiveTime) # suche ob aeltere versionen vorhanden sind finds = self.ZopeFind(self, obj_metatypes=['MPIWGProject']) if not finds: # wenn nicht dann teste ob die aktuelle version schon existiert hat. ad = getattr(self, 'creationTime', '20050101000000') if int(date) > int(ad): return self.REQUEST['URL1'] + "/" + self.getId() else: return self.REQUEST['URL1'] + "/no_project" else: finds.sort(sortProjectsByTime) for find in finds: # gehe durch die alten Projekte und finde das entprechende if (int(find[1].archiveTime) > int(date)) and (int(date) > int(getattr(find[1], 'creationTime', '20050101000000'))): return self.REQUEST['URL1'] + "/" + find[1].getId() # kein passendes gefunden, dann teste ob das aktuelle in frage kommt ad = getattr(self, 'creationTime', '20050101000000') if int(date) > int(ad): return self.REQUEST['URL1'] + "/" + self.getId() else: return self.REQUEST['URL1'] + "/no_project" def saveFromPreview(self, RESPONSE=None): """save content aus preview""" self.WEB_project_description = self.previewTemplate.WEB_project_description[0:] #self.REQUEST.RESPONSE.redirect("./index.html") if RESPONSE is not None: return self.editDescription() def saveEditedContent(self, kupu=None, preview=None, RESPONSE=None): """save Edited content""" # logging.debug("saveEditedContent kupu=%s preview=%s"%(kupu,preview)) if preview: kupu = preview # find content of body tags start = kupu.find("<body>") end = kupu.find("</body>") newcontent = kupu[start + 6:end] if preview: return self.preview(newcontent) self.copyObjectToArchive() self.WEB_project_description = newcontent[0:] #self.REQUEST.RESPONSE.redirect("./index.html") if RESPONSE is not None: return self.editDescription() def getBreadcrumbs(self): """return list of breadcrumbs from here to the root""" crumbs = [] # skip direct parent Folder /projects/ parent = self.aq_parent.aq_parent # get parents breadcrumbs if hasattr(parent, 'getBreadcrumbs'): crumbs = parent.getBreadcrumbs() # try to get acquisition URL from parent if hasattr(parent, 'absolute_url'): baseUrl = "%s/%s/" % (parent.absolute_url(), 'projects') else: baseUrl = "/en/research/projects/" # add in the internal project hierarchy tree = self.getProjectTree() ap = tree.getAncestorsOf(self.getNumber()) # start with grandparents for p in ap: label = shortenString(p.getLabel(), 13) crumbs.append((label, p.getUrl(baseUrl=baseUrl), p)) # add this project crumbs.append((self.getLabel(), self.getUrl(baseUrl=baseUrl), self)) return crumbs # TODO: is this used? def preview(self, description): """preview""" # logging.debug("preview description=%s"%description) tmpPro = getattr(self, "previewTemplate", None) if not tmpPro: tmpPro = MPIWGProject("previewTemplate") self._setObject("previewTemplate", tmpPro) for field in definedFields: setattr(tmpPro, field, getattr(self, field)) tmpPro.WEB_project_description = description[0:] tmpPro.invisible = True pt = PageTemplateFile('zpt/project/edit_preview_frame', globals()).__of__(self) return pt() def isResponsibleScientist(self, key): """teste ob eine Person in der Liste der respl. scientists auftaucht""" for resp in self.getResponsibleScientistsList(): logging.debug("resp=%s key=%s"%(repr(resp),repr(key))) # TODO: we need to get ASCII keys!! if utf8ify(resp.get('key', '')).lower() == utf8ify(key).lower(): return True return False def identifyNames(self, nameList): """Bekommt eine Komma oder Semikolon getrennte Liste mit Name der Form Vorname MittelName(n) Nachname und ordnet diese dann Mitarbeiter IDs zu. Returns a dict with full names as keys and a row of person objects from the database as values. @param nameList """ if nameList.find(";") > -1: # rate Trenner ist ; names = nameList.split(";") else: names = nameList.split(",") # #nameList=nameList.replace(";",",") # falls ; als Trenner ersetze returnNamesDict = {} for name in names: name = name.strip() if not name: continue nameSplitted = name.split(" ") if len(nameSplitted) > 1: # vor und nachname angegeben) lastname = nameSplitted[-1] firstname = nameSplitted[0] else: firstname = "" lastname = nameSplitted[0] # finde Mitarbeiter mit den entsprechenden Name # firstname=self.myCapitalize(firstname).encode('utf-8') # lastname=self.myCapitalize(lastname).encode('utf-8') logging.debug("Search: %s %s %s" % (name, repr(firstname), repr(lastname))) try: # cataloggedNames=self.MembersCatalog(firstName=firstname,lastName=lastname) # TODO: I think this does not work without firstname # try to find names in members db by searching for sub-words cataloggedNames = self.executeZSQL("select * from personal_www where first_name ~* ('\m'||%s||'\M') and last_name ~* ('\m'||%s||'\M')", (firstname, lastname)) if len(cataloggedNames) == 0: # PostgreSQL has a bug with \m and words ending in non-ASCII :-( cataloggedNames = self.executeZSQL("select * from personal_www where %s in (select regexp_split_to_table(lower(first_name), '\s+')) and %s in (select regexp_split_to_table(lower(last_name), '\s+'))", (firstname.lower(), lastname.lower())) except: cataloggedNames = [] logging.error("ERROR: identifyNames %s %s" % sys.exc_info()[0:2]) if len(cataloggedNames) > 0: returnNamesDict[name] = cataloggedNames else: returnNamesDict[name] = [] logging.debug("identified names: %s" % repr(returnNamesDict)) return returnNamesDict def editMPIWGProject(self, fromEdit=None, createNewVersion=True, RESPONSE=None): """edit the project and archive the old version""" logging.debug("editMPIWGProject(fromEdit=%s, createNewVersion=%s)"%(fromEdit,createNewVersion)) if createNewVersion: self.copyObjectToArchive() # archive the object formdata = self.REQUEST.form # set all definedFields for x in definedFields: if formdata.has_key(x): setattr(self, x, unicodify(formdata[x])) if x == 'xdata_05': # changing project number invalidates project tree self.resetProjectTree() completedAt = formdata.get('completedAt') if not self.setCompletedAt(completedAt): RESPONSE.redirect('./editMPIWGBasisEditor?error=dateWrong') startedAt = formdata.get('startedAt') if not self.setStartedAt(startedAt): RESPONSE.redirect('./editMPIWGBasisEditor?error=dateWrong') if self.REQUEST.has_key('active'): self.setActiveFlag(True) else: self.setActiveFlag(False) # make dict of responsible scientists checkedScientists = {} names = {} keys = {} for key in formdata: # gehe durch das Formular keyParts = key.split("_") if keyParts[0] == "responsibleScientist": # wenn es ein Feld der Form reponsibleScientist_nr_KEY gibt nr = keyParts[2] if keyParts[1] == "name": names[nr] = unicodify(formdata[key]) elif keyParts[1] == "key": keys[nr] = formdata[key] for nr in names: name = names[nr] key = keys.get(nr, None) username = None if key: # get username from db member = self.en.getMPIWGRoot().getStaffFolder().getMember(key=key) if member is not None: username = member.getUsername() # schreibe keys und namen in die Liste checkedScientists[names[nr]] = {'name' : name, 'key' : key, 'username' : username} # update responsibleScientistsList self.setResponsibleScientistsList(checkedScientists) self.updateProjectMembers() if fromEdit and (RESPONSE is not None): return self.editBasic() if RESPONSE is not None: RESPONSE.redirect('manage_main') def getContent(self, field, filter=None): """Inhalt des Feldes""" val = getattr(self, field, '') if isinstance(val, list): val = val[0] return val def loadNewFile(self, RESPONSE=None): """einlesen des neuen files""" fileupload = self.REQUEST['fileupload'] if fileupload: file_name = fileupload.filename filedata = fileupload.read() argv = xmlhelper.proj2hash(filedata) # print argv.keys() for arg in definedFields: # print arg,argv[arg],getattr(self,arg) try: temp = argv[arg][0:] # old=getattr(self,arg) setattr(self, arg, temp) # print old,getattr(self,arg) except: """nothing""" if RESPONSE is not None: RESPONSE.redirect('manage_main') def tagTheProject(self, RESPONSE=None): """TAG""" id = self.getId(); tmpl = getattr(self.thesaurus, "main.html") if RESPONSE: RESPONSE.redirect("./thesaurus/main.html?project=" + id) return def moveObjectDigitallibraryToInfoBlock(self): """Move text from 'Object Digitallibrary' to InfoBlock.""" text = self.getRelatedDigitalSources() if text: logging.debug("Moving 'Object Digitallibrary' to InfoBlock: %s"%repr(text)) self.addInfoBlock(block_title='Related digital sources', item_text=text, item_link=None) delattr(self, 'xdata_11') def hasRelatedPublicationsOldVersion(self): """teste ob es related publications gibt""" ret = True; if (getattr(self, 'WEB_related_pub', '') == ''): ret = False; # nichts im alten feld logging.debug("webrel:" + repr(ret)) if (getattr(self, 'WEB_related_pub_copied', False)): ret = False; # alte daten sind schon kopiert worden logging.debug("webrel_copied:" + repr(ret)) publications = self.ZopeFind(self, obj_metatypes=['MPIWGProject_publication']); if(len(publications) > 0): ret = False; # es gibt publicationen in der neuen liste logging.debug("len(publ)" + repr(ret)) return ret; def copyPublicationsToList(self, RESPONSE=None): """copy publications in to list""" publicationTxt = getattr(self, 'WEB_related_pub', '') if isinstance(publicationTxt, list): publicationTxt = publicationTxt[0] pubSplits = publicationTxt.split("<p>") for pubSplit in pubSplits: pubSplit = pubSplit.replace("</p>", "") self.addPublication(pubSplit) setattr(self, "WEB_related_pub_copied", True); if RESPONSE: self.redirect(RESPONSE, 'managePublications') def hasInlineImage(self): """Return the number of inline images in the description.""" text = self.getDescription() cnt = text.count('<p class="picture">') return cnt def copyImageToMargin(self, RESPONSE=None): """copy inline images to marginal images""" # getImages from WEB_project_description description = self.getDescription() text2 = description splitted = text2.split("""<p class="picture">""") imageURLs = [] imageCaptions = [] for split in splitted[1:]: tmp = split.split("</p>") # return repr(splitted[1]) try: imageURLs.append(tmp[0].split("\"")[1].encode('utf-8')) except: try: imageURLs.append(tmp[0].split("src=")[1].split(" ")[0].encode('utf-8')) except: imageURLs.append("") split2 = "</p>".join(tmp[1:]) splitted = split2.split("""<p class="picturetitle">""") if len(splitted) > 1: tmp = splitted[1].split("</p>") imageCaptions.append(tmp[0].encode('utf-8')) else: # keine caption imageCaptions.append("") # eintragen: for imageURL in imageURLs: if not imageURL: # no URL - no image continue filename = imageURL.split("/")[-1] # lege neues images object an, mit leerem bild if filename in self: # existiert das bild schon, dann neuen filenamen filename = "project_image_" + filename if filename in self: # exists too - assume its already converted logging.warn("copyImageToMargin: image %s exists - skipping!"%filename) continue self.addImage(None, imageCaptions[imageURLs.index(imageURL)], filename=filename) # hole die bilddaten aus der url url = self.absolute_url() + "/" + imageURL # url=self.absolute_url()+"/"+filename try: # relative url data = urllib.urlopen(url).read() except: try: # absolute data = urllib.urlopen(self.imageURL).read() except: logging.error("copyImageToMargin: can't open: %s" % url) obj = getattr(self, filename) obj.update_data(data) # clean description logging.debug("copyImageToMargin: description:%s"%repr(description)) dom = ET.fromstring(utf8ify("<html>%s</html>"%description)) for e in dom.findall(".//p[@class='picture']"): # remove contents e.clear() # remove tag e.tag = None for e in dom.findall(".//p[@class='picturetitle']"): # remove contents e.clear() # remove tag e.tag = None # remove html tag dom.tag = None # set as new description description = unicodify(serialize(dom)) logging.debug("copyImageToMargin: new description:%s"%repr(description)) setattr(self, 'WEB_project_description', description) if RESPONSE: self.redirect(RESPONSE, 'manageImages') def updateProjectMembers(self, updateResponsibleScientistsList=False): """Update project-member table.""" # projects are identified by id pid = self.getId() # clear projects_members table self.executeZSQL("delete from projects_members where project_id = %s", [pid]) for m in self.getResponsibleScientistsList(): memberKey = m.get('key', None) if not memberKey or not isinstance(memberKey, basestring): logging.error("updateProjectMembers: not a valid member key: %s" % repr(memberKey)) continue # fill projects_members table self.executeZSQL("insert into projects_members (project_id, member_key) values (%s, %s)", (pid, memberKey)) def manage_addMPIWGProjectForm(self): """form for adding the project""" pt = PageTemplateFile('zpt/project/manage_add_MPIWGProject', globals()).__of__(self) return pt() def manage_addMPIWGProject(self, id, fileupload=None, RESPONSE=None): """method to add a project""" if fileupload: filedata = fileupload.read() argv = xmlhelper.proj2hash(filedata) # print argv newObj = MPIWGProject(id, argv) else: newObj = MPIWGProject(id) self._setObject(id, newObj) if RESPONSE is not None: url = '%s/%s/editBasic'%(self.absolute_url(), id) RESPONSE.redirect(url) class MPIWGProjectFolder(ZDBInterfaceFolder): """Folder of project objects""" meta_type = "MPIWGProjectFolder" security = ClassSecurityInfo() # cached HashTree with project hierarchy _v_projectTree = None def getProjectTree(self): """Return the project hierarchy tree (and cache it). Returns HashTree instance.""" tree = self._v_projectTree if tree is None: tree = HashTree(keySeparator='.', keyFn=getInt) for p in self.objectValues(spec='MPIWGProject'): # add all projects tree.add(p.getNumber(), p) self._v_projectTree = tree # logging.debug("getProjectTree: tree=%s"%(tree.root.getSubtreeAsText())) return tree def getProjectsAsList(self, start=None, active=1, archived=1, depthFirst=True): """Return flattened list of projects, starting from start. active = 0 : all projects active = 1 : active projects active = 2 : inactive projects archived = 0 : all projects archived = 1 : current projects archived = 2 : archived projects """ # logging.debug("getProjectsAsList(start=%s,active=%s,archived=%s)"%(repr(start),active,archived)) tree = self.getProjectTree() node = tree.getNode(start) if node is None: return [] pl = node.getSubtreeAsList(depthFirst=depthFirst) #logging.debug("getProjectsAsList: node=(%s,%s) pl=%s"%(node.key,node.value,[p.getNumber() for p in pl])) # return filtered list return [p for p in pl if (p.checkActive(active) and p.checkArchived(archived))] def getProject(self, projectNumber=None): """Return the matching project""" tree = self.getProjectTree() if projectNumber is not None: return tree.get(projectNumber) return None def getProjectsOfMember(self, key, active=1, archived=1): """Return a list of all projects of a member. @param key: member's key active = 0 : all projects active = 1 : active projects active = 2 : inactive projects archived = 0 : all projects archived = 1 : current projects archived = 2 : archived projects """ projects = [] # search project numbers res = self.executeZSQL("select * from projects_members where lower(member_key) = %s", [key.lower()]) # find projects in folder for r in res: p = self.get(r.project_id, None) # check if active if p is not None and p.checkActive(active) and p.checkArchived(archived): projects.append(p) # sort by project number projects.sort(key=lambda p:[getInt(n) for n in p.getNumber().split('.')]) return projects def getMembersWithProjects(self, onlyActive=True): """Return a list of all members that have projects. @param onlyActive: only active members Returns a list of member objects. """ members = [] sf = self.en.getStaffFolder() res = self.executeZSQL("select distinct member_key from projects_members") if onlyActive: for r in res: m = sf.getMember(key=r.member_key) if m is not None and m.isActive(): members.append(m) else: # not only active members = [sf.getMember(key=r.member_key) for r in res] return members def resetProjectTree(self): """Reset the project tree.""" self._v_projectTree = None security.declareProtected('View management screens', 'changeProjectTree') def changeProjectTree(self, RESPONSE=None): """change the complete tree""" form=self.REQUEST.form onlyArchived=int(form.get("onlyArchived",0)) onlyActive=int(form.get("onlyActive",0)) dep=form.get("dep",None) fields = self.getProjectsAsList(start=dep, archived=onlyArchived, active=onlyActive) logging.info("GOT TREE!----------------------------------------------------") for field in form.keys(): splitted=field.split('_') if (len(splitted)>1) and (splitted[1]=="runningNumber"): #feld hat die Form Nummer_name und runnignNumber nr=int(splitted[0]) # nummer des Datensatzes project = fields[nr] # # change active # if form.has_key('%s_active'%nr): # active flag is set project.setActiveFlag(True) else: project.setActiveFlag(False) # # nummer hat sich geaendert # entryChanged = False; pronum = project.getNumber() formnum = form['%s_number'%nr] if not (pronum == formnum): logging.debug("Changed!Number+++++++++++++++++++++++++++++++++") logging.debug(repr(fields[nr].xdata_05)+" ---> "+ repr(form[str(nr)+'_number'])) entryChanged = True # # completed hat sich geaendert # td = project.transformDate # hole die funktion zum transformieren des datums formstarted = form[str(nr)+'_started'] formcompleted = form[str(nr)+'_completed'] if not (td(project.getCompletedAt()) == td(formcompleted)): logging.info(repr(td(project.getCompletedAt()))+" ---> "+ repr(td(form[str(nr)+'_completed']))) logging.info("Changed!Completed+++++++++++++++++++++++++++++++++") entryChanged = True if not (td(project.getStartedAt()) == td(formstarted)): logging.info(repr(td(project.getStartedAt()))+" ---> "+ repr(td(form[str(nr)+'_started']))) logging.info("Changed!Started+++++++++++++++++++++++++++++++++") entryChanged = True if entryChanged: logging.info("Changed!+++++++++++++++++++++++++++++++++") project.copyObjectToArchive() project.xdata_05 = formnum project.setCompletedAt(formcompleted) project.setStartedAt(formstarted) # reset tree self._v_projectTree = None if RESPONSE is not None: RESPONSE.redirect(self.en.MPIWGrootURL()+'/admin/showTree') security.declareProtected('View management screens', 'updateAllProjectMembers') def updateAllProjectMembers(self, updateResponsibleScientistsList=False): """Re-create responsibleScientistsLists and projects_members table from all current projects.""" # empty table self.executeZSQL('truncate table projects_members') cnt = 0 # go through all projects for p in self.objectValues(spec='MPIWGProject'): cnt += 1 logging.debug("updateAllProjectMembers: updating project %s" % p) p.updateProjectMembers(updateResponsibleScientistsList=updateResponsibleScientistsList) return "updated %s projects!" % cnt security.declareProtected('View management screens', 'updateAllProjects') def updateAllProjects(self, updateResponsibleScientistsList=False, RESPONSE=None): """Patch all current projects for legacy problems.""" cnt = 0 fulllog = "" # go through all projects for id, project in self.ZopeFind(self, obj_metatypes=['MPIWGProject'], search_sub=1): log = "" cnt += 1 # # hasRelatedPublicationsOldVersion # if project.hasRelatedPublicationsOldVersion(): log += "%s: update relatedPublicationsOldVersion!\n"%project.getId() logging.debug("updateAllProjects(%s): update relatedPublicationsOldVersion!"%project.getId()) project.copyPublicationsToList() # # create responsibleScientistsList automatically # if updateResponsibleScientistsList: newScientists = {} names = project.identifyNames(project.getResponsibleScientists()) for name in names: msg = "%s: regenerating responsibleScientistsList: name=%s\n"%(project.getId(), repr(name)) log += msg logging.debug(msg) members = names[name] if len(members) > 0: # take the first matching name username = None if members[0].e_mail: username = re.sub('@mpiwg-berlin\.mpg\.de', '', members[0].e_mail) newScientists[name] = {'name': name, 'key' : members[0].key, 'username' : username} project.setResponsibleScientistsList(newScientists) else: # # old format responsibleScientistsList # memberlist = project.getResponsibleScientistsList() if len(memberlist) > 0 and isinstance(memberlist[0], tuple): log += "%s: updating memberlist!\n"%project.getId() logging.debug("updateAllProjects(%s): updating memberlist" % project.getId()) newScientists = {} for m in memberlist: name = m[0] key = m[1] username = None if key: if isinstance(key, list): key = key[0] # get username from db member = self.en.getMPIWGRoot().getStaffFolder().getMember(key=key) if member is not None: username = member.getUsername() newScientists[name] = {'name': name, 'key' : key, 'username' : username} # set new list project.setResponsibleScientistsList(newScientists) # # old inline images # if project.hasInlineImage(): log += "%s: has inlineImage!\n"%project.getId() logging.debug("updateAllProjects(%s): has inlineImage!"%project.getId()) try: project.copyImageToMargin() except Exception, e: log += "%s: ERROR in copyImageToMargin!\n"%project.getId() logging.debug("updateAllProjects(%s): ERROR in copyImageToMargin: %s"%(project.getId(), e)) # # remove old attributes # if hasattr(project, 'definedFields'): log += "%s: has definedFields!\n"%project.getId() logging.debug("updateAllProjects(%s): has definedFields!"%project.getId()) delattr(project, 'definedFields') # # update related publications # for pub in project.getPublicationList(): if not pub.text: msg = "%s: publication has no text: %s!\n"%(project.getId(), pub) log += msg logging.warn(msg) if not pub.link: msg = "%s: publication has no link either! Deleting: %s!\n"%(project.getId(), pub) log += msg logging.error(msg) project.deletePublication(pub.getId()) else: # hasLinkToBookPage updates the bookId pub.hasLinkToBookPage() # # update RelatedDigitalSources # project.moveObjectDigitallibraryToInfoBlock() # # unicodify # for field in ('WEB_title', 'xdata_01', 'xdata_07', 'xdata_08', 'xdata_11', 'xdata_12', 'xdata_13', 'WEB_project_description', 'WEB_related_pub'): text = getattr(project, field, None) if isinstance(text, str): log += "%s: has non-unicode field %s\n"%(project.getId(), field) logging.debug("updateAllProjects(%s): has has non-unicode field %s\n"%(project.getId(), field)) setattr(project, field, unicodify(text)) fulllog += log if RESPONSE is not None: RESPONSE.write(log) # # remove obsolete static class members (does this make sense?) # if hasattr(MPIWGProject, 'responsibleScientistsList'): log += "MPIWGProject has class member responsibleScientistsList\n" logging.debug("MPIWGProject has class member responsibleScientistsList\n") del MPIWGProject.responsibleScientistsList if hasattr(MPIWGProject, 'projectThumb'): log += "MPIWGProject has class member projectThumb\n" logging.debug("MPIWGProject has class member projectThumb\n") del MPIWGProject.projectThumb log += "\n DONE! updated %s projects!" % cnt fulllog += log if RESPONSE is not None: RESPONSE.write(log) RESPONSE.flush() else: return fulllog def scaleImages(self,REQUEST=None): """scaleImages""" prjs = self.getProjectsAsList() for prj in prjs: prj.scaleImage(REQUEST=REQUEST) logging.debug(prj.getId()) def manage_addMPIWGProjectFolderForm(self): """form for adding a MPIWGProjectFolder""" pt = PageTemplateFile('zpt/project/manage_add_MPIWGProjectFolder', globals()).__of__(self) return pt() def manage_addMPIWGProjectFolder(self, id, title, RESPONSE=None): """add a MPIWGProjectFolder""" newObj = MPIWGProjectFolder(id, title) self._setObject(id, newObj) if RESPONSE is not None: RESPONSE.redirect('manage_main')