view MPIWGRoot.py @ 52:1ed79b33200c

more work on projects and cleanup.
author casties
date Tue, 30 Apr 2013 16:00:56 +0200
parents d456fe185649
children 4600e31a0431
line wrap: on
line source

from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from App.ImageFile import ImageFile

from Products.ZSQLExtend.ZSQLExtend import ZSQLExtendFolder
from Products.ZCatalog.CatalogPathAwareness import CatalogAware
from OFS.Image import Image
from Globals import package_home
import urllib
import string
import re
import os
from types import *
import logging
from OFS.SimpleItem import SimpleItem
from OFS.Folder import Folder
from AccessControl import ClassSecurityInfo
import time
import xml.dom.minidom
import sys
import transaction
import copy
from BeautifulSoup import BeautifulSoup, Comment
from ZODB import FileStorage, DB
from ZEO import ClientStorage


from MPIWGHelper import *
import updatePersonalWWW
from bibliography import *
import MPIWGStaff
from SrvTxtUtils import getInt, getAt, utf8ify, refreshingImageFileIndexHtml


def sortWeight(x,y):
    x1=int(getattr(x[1],'weight','0'))
    y1=int(getattr(y[1],'weight','0'))
    return cmp(x1,y1)


class MPIWGRoot(ZSQLExtendFolder):
    """Stammordner fuer den Web-Server"""

    _v_harvestCache=None
    meta_type='MPIWGRoot'

    manage_options = Folder.manage_options+(
        {'label':'Update personal homepages','action':'updatePersonalwww_html'},
        {'label':'Reindex catalogs','action':'reindexCatalogs'},
        {'label':'Main config','action':'changeMPIWGRootForm'},
        {'label':'add e-mails','action':'showNewDBEntries'},
        #{'label':'update the institutsbibliography','action':'updateInstitutsbiliography'},
        #{'label':'Edit Historical Persons','action':'editHistoricalPersonsForm'},
        #{'label':'Store Historical Persons','action':'storeHistoricalPersons'},
        )

    # TODO: is this used here?
    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'}
    
    # (is this used?)
    folders=['MPIWGProject','Folder','ECHO_Navigation']
    # language of this instance
    lang = 'en'
    # types of objects that show up in navigation
    nav_meta_types = ['MPIWGTemplate','MPIWGLink','MPIWGFolder']

    #
    # templates
    #
    main_template = PageTemplateFile('zpt/www/main_template', globals())
    common_template = PageTemplateFile('zpt/www/common_template', globals())
    mpiwg_css = ImageFile('css/mpiwg.css', globals())
    # make docuviewer_css refreshable for development
    mpiwg_css.index_html = refreshingImageFileIndexHtml


    def getLang(self):
        """returns the default language"""
        return self.lang

    def browserCheck(self):
        """check the browsers request to find out the browser type"""
        bt = {}
        ua = self.REQUEST.get_header("HTTP_USER_AGENT")
        bt['ua'] = ua
        bt['isIE'] = False
        bt['isN4'] = False
        if string.find(ua, 'MSIE') > -1:
            bt['isIE'] = True
        else:
            bt['isN4'] = (string.find(ua, 'Mozilla/4.') > -1)

        try:
            nav = ua[string.find(ua, '('):]
            ie = string.split(nav, "; ")[1]
            if string.find(ie, "MSIE") > -1:
                bt['versIE'] = string.split(ie, " ")[1]
        except: pass

        bt['isMac'] = string.find(ua, 'Macintosh') > -1
        bt['isWin'] = string.find(ua, 'Windows') > -1
        bt['isIEWin'] = bt['isIE'] and bt['isWin']
        bt['isIEMac'] = bt['isIE'] and bt['isMac']
        bt['staticHTML'] = False

        return bt


    def createOrUpdateId_raw(self):
        """create sequence to create ids for bibliography"""
        debug=None
        #suche groesste existierende id
        founds=self.ZSQLQuery("select id from bibliography")
        
        if founds:
            ids=[int(x.id[1:]) for x in founds]
            maximum=max(ids)
            
            id_raw=self.ZSQLQuery("select nextval('id_raw')",debug=debug)
            
            if id_raw:
                self.ZSQLQuery("drop sequence id_raw",debug=debug)
            
            self.ZSQLQuery("create sequence id_raw start %i"%(maximum+1),debug=debug)
        
    
    def queryLink(self,link):
        """append querystring to the link"""
        return "%s?%s"%(link,self.REQUEST.get('QUERY_STRING',''))

    def getKategory(self,url):
        """kategorie"""
        splitted=url.split("/")
        return splitted[4]

    def isNewCapital(self,text=None,reset=None):
        
        if text:
            text=text.upper()
        if reset:
            self.REQUEST['capital']="A"
            return True
        else:
            if len(text)>0 and not (text[0]==self.REQUEST['capital']):
                self.REQUEST['capital']=text[0]
                return True
            else:
                return False
    
    def subNavStatic(self,obj):
        """subnav" von self"""
        subs=self.ZopeFind(obj,obj_metatypes=['MPIWGTemplate','MPIWGLink'])
        subret=[]

        for x in subs:
            if not(x[1].title==""):
                subret.append(x)
        subret.sort(sortWeight)
        return subret
    
    def getSubsections(self, here=None):
        """return sub-navigation elements i.e. elements below sections"""
        p = here
        if p is None:
            p = self
        sec = None
        # descend parents to the root (and remember the last id)
        while p is not None and p.meta_type != 'MPIWGRoot':
            sec = p
            p = p.aq_parent
    
        subsecs = sec.objectItems(self.nav_meta_types)
        subsecs = [s for s in subsecs if s[1].title != ""]
        subsecs.sort(sortWeight)
        return subsecs

    # compatibility
    subNav = getSubsections
                
    def isType(self,object,meta_type):
        """teste ob ein object vom meta_type ist."""
        return (object.meta_type==meta_type)
    
    def isActive(self,name):
        """teste ob subnavigation aktiv"""
        for part in self.REQUEST['URL'].split("/"):
            if part==name:
                return True
        return False
        
    
    def getSections(self):
        """returns a list of all sections i.e. top-level MPIWGFolders"""
        items = self.objectValues(spec='MPIWGFolder')[:]
        items.sort(key=lambda x:int(x.weight))
        return items

    def getSectionStyle(self, name, style=""):
        """returns a string with the given style + '-sel' if the current section == name"""
        if self.getSection() == name:
            return style + '-sel'
        else:
            return style    

    def getPathStyle(self, path, selected, style=""):
        """returns a string with the given style + 'sel' if path == selected."""
        if path == selected:
            return style + 'sel'
        else:
            return style    

    def getFeatures(self, num=None):
        """returns a list of the last num Features"""
        dir = getattr(self, 'features', None)
        if dir is None:
            return []

        items = dir.objectValues(spec='MPIWGFeature')[:]
        items.sort(key=lambda x:int(x.weight))
        if num is not None:
            # take only the last num elements
            items = items[-num:]
        return items

    def getDepartments(self):
        """returns a list of the Departments"""
        dir = getattr(self, 'departments', None)
        if dir is None:
            return []
        
        items = dir.objectValues(spec='MPIWGDepartment')[:]
        items.sort(key=lambda x:int(x.weight))
        return items

    def getDepartment(self, projectNumber=None):
        """returns a Department object"""
        dir = getattr(self, 'departments', None)
        if dir is None:
            return None

        if projectNumber is not None:
            for dep in dir.objectValues(spec='MPIWGDepartment'):
                if dep.getProjectNumber() == projectNumber:
                    return dep
                
        return None


    def getProjectFolder(self):
        """returns the MPIWGProjectFolder"""
        dir = getattr(self, 'projects', None)
        return dir


    def getStaffFolder(self):
        """returns the MPIWGStaffFolder"""
        dir = getattr(self, 'members_test', None) # TODO: fix the test
        return dir


    def getMPIWGRoot(self):
        """returns the MPIWG root"""
        return self


    def MPIWGrootURL(self):
        """returns the URL to the root"""
        return self.absolute_url()

    
    # TODO: make obsolete
    def decode(self, s):
        """unicodify"""
        return unicodify(s)
    
    # TODO: remove
    def replaceNotEmpty(self,format,field):
        """replace not empty"""
        if field and (not field.lstrip()==''):
            return format%field
            #return self.decode(format%field)
        else:
            return ""
        

        
    def redirectIndex_html(self,request):
        #return request['URL1']+'/index_html'
        
        return urllib.urlopen(request['URL1']+'/index_html').read()

    
    def formatBibliography(self,here,found):
        """format"""
        return formatBibliography(here,found)
    
    def getValue(self,fieldStr):
        """Inhalt des Feldes"""
        
        if type(fieldStr)==StringType:
            field=fieldStr
        else:
            field=fieldStr[0]
        try:
            if field[len(field)-1]==";":
                field=field[0:len(field)-1]
        except:

            """nothing"""
        field=re.sub(r';([^\s])','; \g<1>',field)
        return field.encode('utf-8')


    
    def sortedNames(self,list):
        """sort names"""

        def sortLastName(x_c,y_c):
            try:
                x=urllib.unquote(x_c).encode('utf-8','ignore')
            except:
                x=urllib.unquote(x_c)

            try:
                y=urllib.unquote(y_c).encode('utf-8','ignore')
            except:
                x=urllib.unquote(y_c)
                

            
            try:
                last_x=x.split()[len(x.split())-1]
                last_y=y.split()[len(y.split())-1]

            except:

                last_x=""
                last_y=""
            
            
            
            if last_x<last_y:
                return 1
            elif last_x>last_y:
                return -1
            else:
                return 0
            
        list.sort(sortLastName)
        list.reverse()
        
        return list
    
    def __init__(self, id, title):
        """init"""
        self.id=id
        self.title=title


    def urlQuote(self,str):
        """quote"""
        return urllib.quote(str)

    def urlUnQuote(self,str):
        """quote"""
        return urllib.unquote(str)
    

    def changeMPIWGRootForm(self):
        """edit"""
        pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','changeMPIWGRootForm')).__of__(self)
        return pt()

    def changeMPIWGRoot(self,title,connection_id,coneServiceURL,lang=None,autocommit=None,RESPONSE=None):
        """change"""
        self.title=title
        self.connection_id=connection_id
        #self.disciplineList=disciplineList
        #self.themesList=themesList
        self.coneServiceURL=coneServiceURL
        
        if lang is not None:
            self.lang = lang

        self.autocommit = (autocommit == "on")
        if RESPONSE is not None:
            RESPONSE.redirect('manage_main')

    
        
    def updatePublicationDB(self,personId=None):
        """updates the publication db, i.e. copy year and type into the main table"""
        
        if personId:
            founds = self.ZSQLInlineSearch(_table="publications",key_main=personId)
        else:
            founds = self.ZSQLInlineSearch(_table="publications")
            
        for found in founds:
                        
            if found.id_institutsbibliographie and (not found.id_institutsbibliographie =="") and (not found.id_institutsbibliographie =="0"):
                
                entries = self.ZSQLInlineSearch(_table="institutsbiblio",id=found.id_institutsbibliographie)
                for entry in entries:
                    self.ZSQLChange(_table='publications',_identify='oid=%s' % found.oid,year=entry.year,referencetype=entry.reference_type)
                    
            if found.id_gen_bib and (not found.id_gen_bib ==""):
                entries = self.ZSQLInlineSearch(_table="bibliography",id=found.id_gen_bib)
                for entry in entries:
                    self.ZSQLChange(_table='publications',_identify='oid=%s' % found.oid,year=entry.year,referencetype=entry.reference_type)
                    
        return True        
    
    def showNewDBEntries(self):
        """zeige neue Eintraege in der Datenbank ohne e-mail adressen bzw. fuer die noch kein Object angelegt wurde"""
        
        qstr="select * from personal_www where web_object_created='no' and not key=''"
        res=self.ZSQLQuery(qstr)
        
        pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','showNewDBEntries.zpt')).__of__(self)
        return pt(newEntries=res)
   
    def createNewStaffObjects(self,RESPONSE):
        """create new staff object"""
        
        memberFolder=getattr(self,'members')
        args=self.REQUEST.form
        arg_k=args.keys()
        arg_k.remove("submit")
        ret=""
        for key in arg_k:
            k=self.urlUnQuote(key)
          
            qstr="select * from personal_www where key=%s"%self.ZSQLQuote(k)
            res=self.ZSQLQuery(qstr)[0]
            if args[key]!="": #email-adresse wurde eingetragen
                #create the object
                e_mail=args[key]
                try:
                    newObj=MPIWGStaff.MPIWGStaff(e_mail,res.last_name,res.first_name,k)
                    memberFolder._setObject(e_mail,newObj)
                    obj=getattr(memberFolder,e_mail)
                    obj.reindex_object()
                    ret+="Created %s \n"%e_mail
                    created=True
                except:
                    msg="Cannot create new user %s (%s %s)"%(e_mail,sys.exc_info()[0],sys.exc_info()[1])
                    logging.error(msg)
                    ret+=msg+"\n"
                    created=False
                
                if created:
                    qstr="update personal_www set web_object_created='yes',e_mail='%s@mpiwg-berlin.mpg.de' where key=%s"%(e_mail,self.ZSQLQuote(k))
                    self.ZSQLQuery(qstr)
        
        return ret
                   
        
    def generateNewPersonEntry(self,data):
        """generate a new person entry for data, neue personen werden zunaechst nur in der datenbank angelegt """
        
        #memberFolder=getattr(self,'members')
        #create the object
        
#        try:
#            newObj=MPIWGStaff.MPIWGStaff(urllib.quote(data['key']),data['last_name'].encode('utf-8'),data['first_name'].encode('utf-8')) 
#            memberFolder._setObject(urllib.quote(data['key']),newObj)
#        except:
#            return False, "Cannot create new user %s (%s %s)"%(data['key'],sys.exc_info()[0],sys.exc_info()[1])
#        
        
        #create the new entry in the database
        
        
        result,msg=MPIWGStaff.createNewDBEntry(self,data['publish_the_data'],data['key'],data['last_name'],
                                  data['first_name'],data['titles_new'],data['status'],"",
                                  "",data['date_from'],data['date_to'],
                                  data['department'],'',data['funded_by'],
                                  data['e_mail2'],data['current_work'],"yes",data['date_stay_at_mpiwg'],data['group'],"no",data['current_work'])
        
        return result,msg
 
    def updatePersonEntry(self,data,ignoreEntries=None):
        """update an person entry from data. but ignore all fields in ignore Entries"""
        if ignoreEntries is None:
            ignoreEntries = []
            
        #ignoreEntries.append('current_work') # TODO:updatecurrent work
        logging.debug("updatePersonEntry: data=%s ignoreEntries=%s"%(repr(data),repr(ignoreEntries)))
        
        if data['date_to']=="": # wenn date_to leer
             data['date_to']="date_none"
        
        if data['date_from']=="": # wenn date_fromleer
             data['date_from']="date_none"
        msg=""
   
        
        #eintragen
         
        columns=data.keys()
        for x in ignoreEntries:
            logging.debug("updatePersonEntry: ignoring %s"%x)
            try: #falls in ignore entries felder sind, die nicht in columns sind, fange den fehler ab
                columns.remove(x)
            except:
                pass

        
        insert=[]
        for key in columns:
            if data[key]=="date_none": # date_none eintrag wird zu null uebersetzt
                insert.append('%s=null'%key)
            else:
                insert.append(""" "%s"=%s"""%(key,self.ZSQLQuote(data[key])))
            
        insertStr=",".join(insert)
        queryStr="update personal_www SET %s where key='%s'"%(insertStr,data['key'])
        self.ZSQLQuery("SET DATESTYLE TO 'German'")
        self.ZSQLQuery(queryStr)
       
        #currentwork
        #if not (txt==""):
        #    queryStr="INSERT INTO current_work (id_main,current,publish) VALUES ('%s','%s','%s')"%(id,txt,txt_p)
        #
        #    self.ZSQLQuery(queryStr)
        
        return True,msg


    def updatePersonalwww_doIt(self):
        """do the update"""
        args=self.REQUEST.form
        resultSet=self.REQUEST.SESSION['personal_www']['resultSet']
        news=self.REQUEST.SESSION['personal_www']['news']
        conflicts=self.REQUEST.SESSION['personal_www']['conflicts']
        logging.debug("updatePersonalwww_doIt: args=%s\n  resultSet=%s\n  news=%s\n  conflicts=%s"%(args,resultSet,news,conflicts))
        
        ret="<html><body>"
        # generate the new entry
      
        if news and (len(news)>0):
            ret+="<h2>Hinzugef&uuml;gt</h2>"
            ret+="<p>Neueintr&auml;ge erscheinen erst auf der Homepage, wenn ihnen eine e-mail Adresse zugeordnet wurde.</p>"
            ret+="<ul>"
            
        for new in news:
            if args.has_key(self.urlQuote(new.encode('utf-8'))): # entry was selected
                result,msg=self.generateNewPersonEntry(resultSet[new])
                if not result:
                    logging.error("Error (generateNewPersonEntry) %s"%msg)
                    ret+="<li>ERROR: %s %s"%(new.encode('utf-8'),msg)
                else:
                    ret+="<li>OK: %s"%(new.encode('utf-8'))
                    
        if news and (len(news)>0):
            ret+="<p>Neueintr&auml;ge erscheinen erst auf der Homepage, wenn ihnen eine e-mail Adresse zugeordnet wurde.</p>"
            ret+="</ul>"     
        
        # update

        if len(conflicts.keys())>0:
            ret+="<h2>&Auml;nderung des Benutzers &uuml;bernehmen</h2>"
            ret+="<p>Wenn n&ouml;tig in Filemaker-db &auml;ndern:</p>"
            
        # konflicte   
        for conflict in conflicts.keys():
            ignoreEntries=[]
            displayIgnored=[]
            for cf in conflicts[conflict]:
                if args[conflict.encode('utf-8')+'_'+cf[0]]=="stored": #use the stored one
                    ignoreEntries.append(cf[0])  #so ignore field cf[0]       
                    displayIgnored.append(cf)
                    
            if len(displayIgnored)>0:
                ret+="<h3>%s</h3>"%conflict.encode('utf-8')
                ret+="<table border='1'>"
                for iE in displayIgnored:
                    ret+="<tr><td>%s</td><td>%s</td><td>%s</td>"%(iE[0].encode('utf-8'),iE[1].encode('utf-8'),iE[2].encode('utf-8'))
                ret+="</table>"
                
            self.updatePersonEntry(resultSet[conflict],ignoreEntries=ignoreEntries)
         
         # rest
        cl=list(conflicts.keys())
        
        for key in resultSet.keys():
             if key not in cl:
                 self.updatePersonEntry(resultSet[key])
        return ret+"</body></html>"
                     

    def updateInstitutsbiliography(self):
        """update the Institutsbibliogrpahy"""
        self.upDateSQL('personalwww.xml')
        return "<html><body>DONE</body></html>"


    

    def updatePersonalwww_html(self):
        """update form for the homepages web form"""
        pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','updatePersonalwww.zpt')).__of__(self)
        return pt()

    
    def updatePersonalwww(self,uploadfile):
        """update personalwww
        @param uploadfile: file handle auf das file
        """
        dsn=self.getConnectionObj().connection_string
        #dsn="dbname=personalwww"
        resultSet=updatePersonalWWW.importFMPXML(uploadfile)
        news,conflicts=updatePersonalWWW.checkImport(dsn, resultSet)

        self.REQUEST.SESSION['personal_www']={}
        self.REQUEST.SESSION['personal_www']['resultSet']=resultSet
        self.REQUEST.SESSION['personal_www']['news']=news
        self.REQUEST.SESSION['personal_www']['conflicts']=conflicts
        
        pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','updatePersonalwww_check.zpt')).__of__(self)
        return pt()
    

     

    def getAllMembers(self):
        #ret=[]
        
        def sorter(x,y):
            return cmp(x[0].lower(),y[0].lower())
                    
        results=self.MembersCatalog({'isPublished':True})
       
        ret=[(unicodify(", ".join([proj.lastName, proj.firstName])), proj.getKey) for proj in results]
        
        ret.sort(sorter)
        return ret
    
    
    def printAllMembers(self):
        """print"""
        members=self.getAllMembers()
        ret=""
        for x in members:
            ret+="<p>%s</p>"%x
        return ret
    
        
    def makeList(self,entry):
        """makes a list out of one entry or repeat a list"""
        if type(entry) is StringType:
            return [entry]
        else:
            return entry

    def getTreeRSS(self,dep=None,date=None,onlyActive=1,onlyArchived=0):
        """generateTree"""
        rss="""<?xml version="1.0" encoding="utf-8"?>
                 <rss version="2.0">
                   <channel>"""
        
        for obj in self.getTree(dep, date, onlyActive, onlyArchived):
            linkStr="""<link>http://www.mpiwg-berlin.mpg.de/en/research/projects/%s</link>"""
            rss+="""<item>"""
            rss+=linkStr%obj[3].getId()
            rss+="""</item>"""
            if hasattr(obj[3],'publicationList'):
	        rss+="""<item>"""
                rss+=linkStr%(obj[3].getId()+"/publicationList");
                rss+="""</item>"""
        rss+="""</channel>
        </rss>"""

        return rss

        
    def getRelativeUrlFromPerson(self,list):
        """get urls to person list"""
        ret=[]
        persons=list.split(";")
        for person in persons:
            
            if len(person)>1: #nicht nur Trennzeichen
                splitted=person.split(",")
                if len(splitted)==1:
                    splitted=person.split(" ")
                splittedNew=[re.sub(r'\s(.*)','$1',split) for split in splitted]
                if splittedNew[0]=='':
                    del splittedNew[0]
                search=string.join(splittedNew,' AND ')
                
                if not search=='':

                    try:
                        proj=self.MembersCatalog({'title':search})
                    except:
                        proj=None

                if proj:
                    #ret.append("<a href=%s >%s</a>"%(proj[0].absolute_url,person.encode('utf-8')))
                    ret.append("<a href=%s >%s</a>"%('members/'+proj[0].id+'/index.html',person))
                else:
                    #ret.append("%s"%person.encode('utf-8'))
                    ret.append("%s"%person)
        return string.join(ret,";")
        
    def getMemberIdFromKey(self,key):
        """gibt die ensprechende id  im members Ordner zum key"""
        
        if key=="":
            return ""
        try:
            key=utf8ify(key)
            catalogged=self.MembersCatalog({'getKey':key})
            if len(catalogged)==0:
                return ""
            else:
                return catalogged[0].getObject().getId()
        
        except:
            return ""

            

     
            
def manage_addMPIWGRootForm(self):
    """form for adding the root"""
    pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMPIWGRootForm.zpt')).__of__(self)
    return pt()

def manage_addMPIWGRoot(self,id,title,connection_id="",RESPONSE=None):
    """add a root folder"""
    newObj=MPIWGRoot(id,title)
    self._setObject(id,newObj)
    ob=getattr(self,id)
    setattr(ob,'connection_id',connection_id)
    if RESPONSE is not None:
        RESPONSE.redirect('manage_main')