view MPIWGRoot.py @ 284:1a103b073c72 default tip

make favicon url host and schema relative.
author casties
date Thu, 25 Jun 2015 17:44:57 +0200
parents 5584046a6a04
children
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

from Products.ZSQLExtend.ZSQLExtend import ZSQLExtendFolder

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


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', globals())



    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 shortenString(self, s, l, ellipsis='... '):
        """returns a string of length l (or l-1) by omitting characters in the middle of s, replacing with ellipsis."""
        return shortenString(s, l, ellipsis=ellipsis)

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

    
   
    
    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.members.executeZSQL(qstr)
        
        pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','showNewDBEntries.zpt')).__of__(self)
        return pt(newEntries=res)
   

                   
        
    def generateNewPersonEntry(self,data):
        """generate a new person entry for data, neue personen werden zunaechst nur in der datenbank angelegt """
        logging.debug("generateNewPersonEntry(%s)"%repr(data))
        #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=self.members.createNewDBEntry(data['publish_the_data'],data['key'].replace("MPIWG:",""),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         
        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: make sure default datestyle is DMY
        member.changeData(data)
        

  
    
    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:
            logging.debug("updatePersonalwww_doIt: adding %s"%repr(new))
            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+="</ul>"
            ret+="<p>New entries will be visible on the webpage when an email address has been assigned.</p>"
        else:
            ret+="</ul>"
        
        # update

        if len(conflicts.keys())>0:
            ret+="<h2>Accepted changes to user entries</h2>"
            ret+="<p>Change Filemaker-db when necessary.</p>"
            
        # conflicts   
        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'>"
                ret+="<tr><th>Field</th><th>Web Version</th><th>FM Version</th></tr>"
                for iE in displayIgnored:
                    ret+="<tr><td>%s</td><td>%s</td><td>%s</td></tr>"%(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>Updated user entries</h2>"
            ret += "<ul>"
            
        for key in resultSet.keys():
            if key not in cl:
                self.updatePersonEntry(resultSet[key])
                ret+="<li>%s %s (%s)</li>"%(resultSet[key].get('first_name','').encode('utf-8'), resultSet[key].get('last_name','').encode('utf-8'), key.encode('utf-8'))
                
        if len(resultSet.keys()) > 0:
            ret += "</ul>"

        ret += "<p>Done.</p>"
        return ret+"</body></html>"
                     

    """update form for the homepages web form"""
    updatePersonalwww_html = PageTemplateFile('zpt/updatePersonalwww', globals())

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

        resultSet={}
        for key in resultSetTmp.keys():
            # TODO: properly fix MPIWG: id problem
            if key.startswith('MPIWG:'):
                logging.error("Invalid person key %s!"%key)
                # strip MPIWG: from key
                newkey = key.replace('MPIWG:','')
                # replace key in data
                resultSetTmp[key]['key'] = newkey
                # replace key in resultSet
                resultSet[newkey]=resultSetTmp[key];
            
            else:
                # copy entry
                resultSet[key] = resultSetTmp[key]
        
        news,conflicts=updatePersonalWWW.checkImport(dsn, resultSet)
        
        self.REQUEST.SESSION['personal_www'] = {'resultSet': resultSet, 'news': news, 'conflicts': conflicts}
        
        pt=PageTemplateFile('zpt/updatePersonalwww_check', globals()).__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')