view MPIWGRoot.py @ 188:16d55695f1c8

fix updating staff entries through "Update personal homepages". (creating new entries doesn't work)
author casties
date Fri, 14 Jun 2013 17:36:09 +0200
parents 3ea224968f95
children cc5198541af8
line wrap: on
line source

from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from App.ImageFile import ImageFile
from Globals import package_home
import string
import os
import logging
from OFS.Folder import Folder
import sys

from Products.ZSQLExtend.ZSQLExtend import ZSQLExtendFolder

import MPIWGHelper
import updatePersonalWWW
import MPIWGStaff
from SrvTxtUtils import getInt, unicodify, refreshingImageFileIndexHtml, getDateString


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'},
        )
    
    # (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 mpiwg_css refreshable for development
    mpiwg_css.index_html = refreshingImageFileIndexHtml
    jquery_js = ImageFile('js/jquery.js', globals())
    mpiwg_js = ImageFile('js/mpiwg.js', globals())
    # make mpiwg_js refreshable for development
    mpiwg_js.index_html = refreshingImageFileIndexHtml
    # ZMI
    changeMPIWGRootForm = PageTemplateFile('zpt/root/manage_change')



    def __init__(self, id, title):
        """init"""
        self.id=id
        self.title=title


    # 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 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 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 getDateString(self, **args):
        """Return a formatted date string."""
        return getDateString(**args)

    
    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(spec=self.nav_meta_types)
        subsecs = [s for s in subsecs if s[1].title != ""]
        subsecs.sort(key=lambda x:getInt(getattr(x[1], 'weight', '0')))
        return subsecs

    # compatibility
    subNav = getSubsections
                

    def getSections(self):
        """returns a list of all sections i.e. top-level MPIWGFolders"""
        items = self.objectValues(spec='MPIWGFolder')
        items.sort(key=lambda x:getInt(getattr(x, 'weight', '0')))
        return items


    getPathStyle = MPIWGHelper.getPathStyle
    
    
    def getFeatures(self, num=None, reverse=False):
        """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), reverse=reverse)
        if num is not None:
            # take only the last num elements
            items = items[-num:]
        return items


    def getFeatureAuthorMap(self):
        """Return a map of authors of features.
        
        Returns a dict with author names and a list of feature numbers.
        """
        features = self.getFeatures()
        authors = {}
        # build dict of unique authors and features
        fno = 0 
        for f in features:
            author = f.getAuthor()
            fno += 1
            if author:
                for a in author.split(';'):
                    a = a.strip()
                    if a in authors:
                        authors[a].append(fno)
                    else:
                        authors[a] = [fno]
                        
        return authors                
                

    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, id=None, projectNumber=None):
        """returns a Department object"""
        dir = getattr(self, 'departments', None)
        if dir is None:
            return None

        if id is not None:
            return dir.get(id, 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', 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)
    

    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')

    
    # TODO: is this used?
    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,newdata,ignoreEntries=None):
        """update an person entry from newdata. but ignore all fields in ignore Entries"""
        data = newdata.copy()
        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']=None
        
        if data['date_from']=="": # wenn date_fromleer
            data['date_from']=None
           
        #eintragen
         
        columns=data.keys()
        for x in ignoreEntries:
            logging.debug("updatePersonEntry: ignoring %s"%x)
            if x in data:
                del data[x]

        member = self.getStaffFolder().getMember(key = data['key'])
        if member is None:
            logging.error("updatePersonEntry: member (key=%s) not found!"%repr(data['key']))
            return
        
        # TODO: change date handling
        self.getStaffFolder().executeZSQL("SET DATESTYLE TO 'German'")
        member.changeData(data)
        
#        msg=""
#         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)
#        
#         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>Added</h2>"
            ret+="<ul>"
            
        for new in news:
            if args.has_key(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>New entries will be visible on the webpage when an email address has been assigned.</p>"
            ret+="</ul>"
        
        # update

        if len(conflicts.keys())>0:
            ret+="<h2>Accepted changes to user entries</h2>"
            ret+="<p>Change Filemaker-db when necessary.</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())
        
        if len(resultSet.keys()) > 0:
            ret += "<h2>Updating user entries</h2>"
            ret += "<ul>"
            
        for key in resultSet.keys():
            if key not in cl:
                self.updatePersonEntry(resultSet[key])
                ret+="<li>%s</li>"%(key.encode('utf-8'))
                
        if len(resultSet.keys()) > 0:
            ret += "</ul>"

        ret += "<p>Done.</p>"
        return ret+"</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'] = {'resultSet': resultSet, 'news': news, 'conflicts': conflicts}
        
        pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','updatePersonalwww_check.zpt')).__of__(self)
        return pt()
    

    def getAllProjectPublications(self):
            """get all publications"""
            fw=file("/tmp/allProjectPublications","w")
            projects =self.projects.getProjectsAsList(None,active=0,archived=0)
           
            for project in projects:
                logging.debug(project)
                if hasattr(project,'publicationList'):
                    try:
                        x =project.publicationList.bibliolist.data
                    
                    except:
                        logging.error("Can't do: %s"%project.absolute_url())
                        continue
                
                    id=project.getId()
                    for l in x.split("\n"):
                        fw.write("%s,%s\n"%(id,l))
                    fw.flush()
                
            fw.close()
            
    def getBookLinkFromID(self,ident):
        """holt die url auf eine buchseite, bekommt identifier MPIWG-Book:XXXX"""
       
        splitted = ident.split(":")
        if len(splitted)!=2:
            logging.debug("getBookLinkFromID: %s not a valid book id, should be MPIWG-Book:XXXX"%ident)
            return ""
        
        books = getattr(self,'books',None)
        if books is None:
            logging.debug("getBookLinkFromID: cannot find books page folder")
            return ""
        
        
        bookobj = getattr(books,splitted[1],None)
        
        if bookobj is None:
            logging.debug("getBookLinkFromID: %s not a valid book id"%ident)
            return ""
        
    
        return "books/"+splitted[1]
    

def manage_addMPIWGRootForm(self):
    """form for adding the root"""
    pt=PageTemplateFile('zpt/root/addMPIWGRootForm', globals()).__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')