Util Page
from google.appengine.api import users
from google.appengine.ext.db import Key, run_in_transaction
from google.appengine.ext.db import delete as db_delete
from db import Pagedb, Userdb
 
class NotFindPageError(Exception):
    '''找不到頁面的例外'''
    def __init__(self, value = 'not find the page.'):
        self.value = value
    def __str__(self):
        return repr(self.value)
 
def findPage(user, page_title = None, tag = None, **kew):
    '''
    return : 尋找到的頁面實體列表(Pagedb in list)
    argument :
    page_title = 頁面名稱
    user = 建立頁面的使用者,User類別
    tag = 尋找特定tag
    '''
    if not page_title and not tag and not kew:
        raise ValueError, "must have one more argument"
    #整理參數
    if kew.has_key('page_title'):
        page_title = kew['page_title']
    if kew.has_key('tag'):
        tag = kew['tag']
    #建立gql語句
    if page_title and tag :
        gql = "WHERE pagetitle = '" + page_title + "' and tag = '" + tag + "'"
    elif page_title:
        gql = "WHERE pagetitle = '" + page_title + "'"
    elif tag :
        gql = "WHERE tag = '" + tag + "'"
    try:
        if isinstance(user, users.User):
            gql += ' and author = :author and isnew = :isnew'
            pagedbs = Pagedb.gql(gql, author = user, isnew = True).fetch(100)
        else:
            pagedbs = Pagedb.gql(gql, page_title).fetch(100) #取出指定標題的頁面
    except:
        raise NotFindPageError
    if not pagedbs:
        raise NotFindPageError
    return pagedbs
 
def updatePage(pageData, oldPagedb):
    '''
    更新頁面的方法
    argument :
    pageData : 要更新的頁面內容(dict)
    pagedb : 要更新的頁面物件(Pagedb)
    '''
    run_in_transaction(__updatePage, pageData, oldPagedb)
    updateTag(pageData, oldPagedb.author)
 
def __updatePage(pageData, oldPagedb):
    '''更新頁面的方法實作,用交易執行'''
    newPagedb = Pagedb.copy(oldPagedb)
    if 'title' in pageData:
        newPagedb.title = pageData['title']
    if 'pagetitle' in pageData:
        newPagedb.pagetitle = pageData['pagetitle']
    if 'content' in pageData:
        newPagedb.content = pageData['content']
    if 'tag' in pageData:
        newPagedb.tag = pageData['tag']
    else:
        raise TypeError, 'no data need update.'
    newPagedb.previous = oldPagedb
    newPagedb.isnew = True
    oldPagedb.isnew = False
    oldPagedb.put()
    newPagedb.put()
 
def createPage(pageData, user = None):
    '''
    建立一個頁面
    argument :
    user : User物件, 建立者
    pageData : 頁面資料(dict).其中包含下列內容 :
        建立者(Userdb) : user , 如果參數user有傳入則優先使用. 如果沒有參數也沒有參數user則以目前的登入者為主.
        標題 : title
        頁面標題 : pagetitle
        內容 : content
        標籤 : tag
    '''
    if 'user' not in pageData:
        if not user:
            user = users.get_current_user()
        if not user:
            raise ValueError, 'no user login'
        pageData['user'] = Userdb.get_by_key_name(user.nickname())
    if not pageData['user']:
        raise ValueError, pageData
    #進入交易模式
    run_in_transaction(__createPage, pageData)
    updateTag(pageData, pageData['user'])
 
def __createPage(pageData):
    '''建立頁面的方法實作,用交易執行'''
    pagedb = Pagedb(#新實體建立
            parent = pageData['user'],
            tag = pageData['tag'],
            isnew = True,
            title = pageData['title'],
            pagetitle = pageData['pagetitle'],
            content = pageData['content']
            )
    pagedb.put()#放入,結束
 
def updateTag(page,user):
    '''
    更新標籤
    argument :
        page : Page物件或是dict並且含有tag內容
        user : user物件或是Userdb物件, 擁有標籤所屬的頁面的使用者
    '''
    if isinstance(page, dict):
        tag = page['tag']
    elif isinstance(page, Pagedb):
        tag = page.tag
    else:
        raise TypeError, "page type error: %s" % type(page)
    if not isinstance(user, Userdb):
        user = Userdb.get_by_key_name(user.nickname())
    run_in_transaction(__updateTag, tag, user)
    __checkTag(user)
 
def __updateTag(tags, user):
    '''實際執行的方法,用交易執行'''
    for tag in tags:
        if not tag in user.tags:#沒有在List中的標籤加入List中
            user.tags.append(tag)
    user.put()
 
def __checkTag(userdb):
    '''
    檢查是否有未使用的標籤
    若未使用將會被去除
    '''
    for tag in userdb.tags:
        pages = Pagedb.gql('WHERE tag = :tag AND author = :author',tag = tag , author = userdb.user).count()
        if not pages:#數量是0則移除標籤
            userdb.tags.remove(tag)
    userdb.put()
 
def create_by_first_use(user = None):
    '''
    對第一次使用的使用者初始化
    第一次使用的使用者需要呼叫
    argument :
        user : 需要初始化的使用者(users.User)
    '''
    if not user:
        user = users.get_current_user()
        if not user:
            raise ValueError, 'user not login.'
    if not isinstance(user, users.User):
        raise TypeError, 'argument must be users.User object'
    newUser = Userdb(user = user,sitetitle = user.nickname() + "'s site",key_name = user.nickname())
    newUser.put()
    #建立頁面列表
    listData = {
                'pagetitle' : 'mylist',
                'title' : u'mylist 我的列表',
                'content' : '[[module pagelist]]',
                'tag' : ['nav']
                }
    createPage(listData, user)
 
def deletePage(pagedb):
    '''
    刪除頁面
    argument :
        pagedb : 要被刪除的頁面資料(Pagedb)
    '''
    deletelist = []
    while pagedb:
        deletelist.append(pagedb)
        pagedb = pagedb.previous
    db_delete(deletelist)
 
def __deletePage(pagedb):
    if pagedb.previous :
        __deletePage(pagedb.previous)
    pagedb.delete()