<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
 * Typecho Blog Platform
 *
 * @copyright  Copyright (c) 2008 Typecho team (http://www.typecho.org)
 * @license    GNU General Public License 2.0
 * @version    $Id$
 */

/**
 * XmlRpc接口
 *
 * @author blankyao
 * @category typecho
 * @package Widget
 * @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
 * @license GNU General Public License 2.0
 */
class Widget_XmlRpc extends Widget_Abstract_Contents implements Widget_Interface_Do
{
    /**
     * 当前错误
     *
     * @access private
     * @var IXR_Error
     */
    private $error;
    
    /**
     * wordpress风格的系统选项
     * 
     * @access private
     * @var array
     */
    private $_wpOptions;
    
    /**
     * 已经使用过的组件列表
     * 
     * @access private
     * @var array
     */
    private $_usedWidgetNameList = array();
    
    /**
     * 获取扩展字段
     * 
     * @access private
     * @param Widget_Abstract_Contents $content
     * @return array
     */
    private function getPostExtended(Widget_Abstract_Contents $content)
    {
        //根据客户端显示来判断是否显示html代码
        $agent = $this->request->getAgent();
        $text = '';
        
        switch (true) {
            case false !== strpos($agent, 'wp-iphone'):   // wordpress iphone客户端
            case false !== strpos($agent, 'wp-blackberry'):  // 黑莓
            case false !== strpos($agent, 'wp-andriod'):  // andriod
            case false !== strpos($agent, 'plain-text'):  // 这是预留给第三方开发者的接口, 用于强行调用非所见即所得数据
            case $this->options->xmlrpcMarkdown:
                $text = $content->text;
                break;
            default:
                $text = $content->content;
                break;
        }
    
        $post = explode('<!--more-->', $text, 2);
        return array(
            $this->options->xmlrpcMarkdown? $post[0] : Typecho_Common::fixHtml($post[0]),
            isset($post[1]) ? Typecho_Common::fixHtml($post[1]) : NULL
        );
    }
    
    /**
     * 将typecho的状态类型转换为wordperss的风格
     * 
     * @access private
     * @param string $status typecho的状态
     * @param string $type 内容类型
     * @return string
     */
    private function typechoToWordpressStatus($status, $type = 'post')
    {
        if ('post' == $type) {
            /** 文章状态 */
            switch ($status) {
                case 'waiting':
                    return 'pending';
                case 'publish':
                case 'draft':
                case 'private':
                    return $status;
                default:
                    return 'publish';
            }
        } else if ('page' == $type) {
            switch ($status) {
                case 'publish':
                case 'draft':
                case 'private':
                    return $status;
                default:
                    return 'publish';
            }
        } else if ('comment' == $type) {
            switch ($status) {
                case 'publish':
                case 'approved':
                    return 'approve';
                case 'waiting':
                    return 'hold';
                case 'spam':
                    return $status;
                default:
                    return 'approve';
            }
        }
        
        return '';
    }
    
    /**
     * 将wordpress的状态类型转换为typecho的风格
     * 
     * @access private
     * @param string $status wordpress的状态
     * @param string $type 内容类型
     * @return string
     */
    private function wordpressToTypechoStatus($status, $type = 'post')
    {
        if ('post' == $type) {
            /** 文章状态 */
            switch ($status) {
                case 'pending':
                    return 'waiting';
                case 'publish':
                case 'draft':
                case 'private':
                case 'waiting':
                    return $status;
                default:
                    return 'publish';
            }
        } else if ('page' == $type) {
            switch ($status) {
                case 'publish':
                case 'draft':
                case 'private':
                    return $status;
                default:
                    return 'publish';
            }
        } else if ('comment' == $type) {
            switch ($status) {
                case 'approve':
                case 'publish':
                case 'approved':
                    return 'approved';
                case 'hold':
                case 'waiting':
                    return 'waiting';
                case 'spam':
                    return $status;
                default:
                    return 'approved';
            }
        }
        
        return '';
    }
    
    /**
     * 代理工厂方法,将类静态化放置到列表中
     *
     * @access public
     * @param string $alias 组件别名
     * @param mixed $params 传递的参数
     * @param mixed $request 前端参数
     * @param boolean $enableResponse 是否允许http回执
     * @return object
     * @throws Typecho_Exception
     */
    private function singletonWidget($alias, $params = NULL, $request = NULL, $enableResponse = true)
    {
        $this->_usedWidgetNameList[] = $alias;
        return Typecho_Widget::widget($alias, $params, $request, $enableResponse);
    }

    /**
     * 如果这里没有重载, 每次都会被默认执行
     *
     * @access public
     * @param boolen $run 是否执行
     * @return void
     */
    public function execute($run = false)
    {
        if ($run) {
            parent::execute();
        }

        // 临时保护模块
        $this->security->enable(false);
        
        $this->_wpOptions = array(
			// Read only options
			'software_name'		=> array(
				'desc'			=> _t( '软件名称' ),
				'readonly'		=> true,
				'value'			=> $this->options->software
			),
			'software_version'	=> array(
				'desc'			=> _t( '软件版本' ),
				'readonly'		=> true,
				'value'			=> $this->options->version
			),
			'blog_url'			=> array(
				'desc'			=> _t( '博客地址' ),
				'readonly'		=> true,
				'option'		=> 'siteUrl'
			),
            'home_url'          => array(
                'desc'          => _t( '博客首页地址' ),
                'readonly'      => true,
                'option'        => 'siteUrl'
            ),
            'login_url'         => array(
                'desc'          => _t( '登录地址' ),
                'readonly'      => true,
                'value'         => $this->options->siteUrl.'admin/login.php'
            ),
             'admin_url'        => array(
                'desc'          => _t( '管理区域的地址' ),
                'readonly'      => true,
                'value'         => $this->options->siteUrl.'admin/'
            ),

            'post_thumbnail'    => array(
                'desc'          => _t( '文章缩略图' ),
                'readonly'      => true,
                'value'         => false
            ),

			// Updatable options
			'time_zone'			=> array(
				'desc'			=> _t( '时区' ),
				'readonly'		=> false,
				'option'		=> 'timezone'
			),
			'blog_title'		=> array(
				'desc'			=> _t( '博客标题' ),
				'readonly'		=> false,
				'option'			=> 'title'
			),
			'blog_tagline'		=> array(
				'desc'			=> _t( '博客关键字' ),
				'readonly'		=> false,
				'option'		=> 'description'
			),
			'date_format'		=> array(
				'desc'			=> _t( '日期格式' ),
				'readonly'		=> false,
				'option'		=> 'postDateFormat'
			),
			'time_format'		=> array(
				'desc'			=> _t( '时间格式' ),
				'readonly'		=> false,
				'option'		=> 'postDateFormat'
			),
			'users_can_register'	=> array(
				'desc'			=> _t( '是否允许注册' ),
				'readonly'		=> false,
				'option'		=> 'allowRegister'
			)
		);
    }

    /**
     * 检查权限
     *
     * @access public
     * @return void
     */
    public function checkAccess($name, $password, $level = 'contributor')
    {
        if ($this->user->login($name, $password, true)) {
            /** 验证权限 */
            if ($this->user->pass($level, true)) {
                $this->user->execute();
                return true;
            } else {
                $this->error = new IXR_Error(403, _t('权限不足'));
                return false;
            }
        } else {
            $this->error = new IXR_Error(403, _t('无法登陆, 密码错误'));
            return false;
        }
    }

    /**
     * 获取pageId指定的page
     * about wp xmlrpc api, you can see http://codex.wordpress.org/XML-RPC
     *
     * @param int $blogId
     * @param int $pageId
     * @param string $userName
     * @param string $password
     * @access public
     * @return struct $pageStruct
     */
    public function wpGetPage($blogId, $pageId, $userName, $password)
    {
        /** 检查权限 */
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }

        /** 获取页面 */
        try {
            /** 由于Widget_Contents_Page_Edit是从request中获取参数, 因此我们需要强行设置flush一下request */
            /** widget方法的第三个参数可以指定强行转换传入此widget的request参数 */
            /** 此组件会进行复杂的权限检测 */
            $page = $this->singletonWidget('Widget_Contents_Page_Edit', NULL, "cid={$pageId}");
        } catch (Typecho_Widget_Exception $e) {
            /** 截获可能会抛出的异常(参见 Widget_Contents_Page_Edit 的 execute 方法) */
            return new IXR_Error($e->getCode(), $e->getMessage());
        }

        /** 对文章内容做截取处理，以获得description和text_more*/
        list($excerpt, $more) = $this->getPostExtended($page);

        $pageStruct = array(
            'dateCreated'   => new IXR_Date($this->options->timezone + $page->created),
            'userid'        => $page->authorId,
            'page_id'       => $page->cid,
            'page_status'   => $this->typechoToWordpressStatus($page->status, 'page'),
            'description'   => $excerpt,
            'title'         => $page->title,
            'link'          => $page->permalink,
            'permaLink'     => $page->permalink,
            'categories'    => $page->categories,
            'excerpt'       => $page->description,
            'text_more'     => $more,
            'mt_allow_comments' => intval($page->allowComment),
            'mt_allow_pings'    => intval($page->allowPing),
            'wp_slug'       => $page->slug,
            'wp_password'   => $page->password,
            'wp_author'     => $page->author->name,
            'wp_page_parent_id' => '0',
            'wp_page_parent_title' => '',
            'wp_page_order' => $page->order,     //meta是描述字段, 在page时表示顺序
            'wp_author_id'  => $page->authorId,
            'wp_author_display_name' => $page->author->screenName,
            'date_created_gmt'  => new IXR_Date($page->created),
            'custom_fields'     => array(),
            'wp_page_template'  =>  $page->template
        );

        return $pageStruct;
    }

    /**
     * 获取所有的page
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @access public
     * @return array(contains $pageStruct)
     */
    public function wpGetPages($blogId, $userName, $password)
    {
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }

        /** 过滤type为page的contents */
        /** 同样需要flush一下, 需要取出所有status的页面 */
        $pages = $this->singletonWidget('Widget_Contents_Page_Admin', NULL, 'status=all');

        /** 初始化要返回的数据结构 */
        $pageStructs = array();

        while ($pages->next()) {
            /** 对文章内容做截取处理，以获得description和text_more*/
            list($excerpt, $more) = $this->getPostExtended($pages);
            $pageStructs[] = array(
                'dateCreated'            => new IXR_Date($this->options->timezone + $pages->created),
                'userid'                 => $pages->authorId,
                'page_id'                => intval($pages->cid),
                /** todo:此处有疑问 */
                'page_status'            => $this->typechoToWordpressStatus($pages->status, 'page'),
                'description'            => $excerpt,
                'title'                  => $pages->title,
                'link'                   => $pages->permalink,
                'permaLink'              => $pages->permalink,
                'categories'             => $pages->categories,
                'excerpt'                => $pages->description,
                'text_more'              => $more,
                'mt_allow_comments'      => intval($pages->allowComment),
                'mt_allow_pings'         => intval($pages->allowPing),
                'wp_slug'                => $pages->slug,
                'wp_password'            => $pages->password,
                'wp_author'              => $pages->author->name,
                'wp_page_parent_id'      => 0,
                'wp_page_parent_title'   => '',
                'wp_page_order'          => intval($pages->order),     //meta是描述字段, 在page时表示顺序
                'wp_author_id'           => $pages->authorId,
                'wp_author_display_name' => $pages->author->screenName,
                'date_created_gmt'       => new IXR_Date($pages->created),
                'custom_fields'          => array(),
                'wp_page_template'       =>  $pages->template
            );
        }

        return $pageStructs;
    }

    /**
     * 撰写一个新page
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @param struct $content
     * @param bool $publish
     * @access public
     * @return void
     */
    public function wpNewPage($blogId, $userName, $password, $content, $publish)
    {
        if (!$this->checkAccess($userName, $password, 'editor')) {
            return $this->error;
        }
        $content['post_type'] = 'page';
        $this->mwNewPost($blogId, $userName, $password, $content, $publish);
    }

    /**
     * 删除pageId指定的page
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @param int $pageId
     * @access public
     * @return bool
     */
    public function wpDeletePage($blogId, $userName, $password, $pageId)
    {
        if (!$this->checkAccess($userName, $password, 'editor')) {
            return $this->error;
        }

        /** 删除页面 */
        try {
            /** 此组件会进行复杂的权限检测 */
            $this->singletonWidget('Widget_Contents_Page_Edit', NULL, "cid={$pageId}", false)->deletePage();
        } catch (Typecho_Widget_Exception $e) {
            /** 截获可能会抛出的异常(参见 Widget_Contents_Page_Edit 的 execute 方法) */
            return new IXR_Error($e->getCode(), $e->getMessage());
        }

        return true;
    }

    /**
     * 编辑pageId指定的page
     *
     * @param int $blogId
     * @param int $pageId
     * @param string $userName
     * @param string $password
     * @param struct $content
     * @param bool $publish
     * @access public
     * @return bool
     */
    public function wpEditPage($blogId, $pageId, $userName, $password, $content, $publish)
    {
        $content['type'] = 'page';
        $this->mwEditPost($blogId, $pageId, $userName, $password, $content, $publish);
    }


    /**
     * 编辑postId指定的post 
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @param int $postId
     * @param struct $content
     * @access public
     * @return bool
     */
    public function wpEditPost($blogId, $userName, $password, $postId, $content)
    {

        $post = $this->singletonWidget('Widget_Archive', 'type=single', 'cid=' . $postId, false);
        if ($post->type == 'attachment') {
            $attachment['title'] = $content['post_title'];
            $attachment['slug'] = $content['post_excerpt'];

            $text = unserialize($post->text);
            $text['description'] = $content['description'];

            $attachment['text'] = serialize($text);

            /** 更新数据 */
            $updateRows = $this->update($attachment, $this->db->sql()->where('cid = ?', $postId));
            return true;
        }
        return $this->mwEditPost($blogId, $postId, $userName, $password, $content);
    }

    /**
     * 获取page列表，没有wpGetPages获得的详细
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @access public
     * @return array
     */
    public function wpGetPageList($blogId, $userName, $password)
    {
        if (!$this->checkAccess($userName, $password, 'editor')) {
            return ($this->error);
        }
        $pages = $this->singletonWidget('Widget_Contents_Page_Admin', NULL, 'status=all');
        /**初始化*/
        $pageStructs = array();

        while ($pages->next()) {
            $pageStructs[] = array(
                'dateCreated'       => new IXR_Date($this->options->timezone + $pages->created),
                'date_created_gmt'  => new IXR_Date($this->options->timezone + $pages->created),
                'page_id'           => $pages->cid,
                'page_title'        => $pages->title,
                'page_parent_id'    => '0',
            );
        }

        return $pageStructs;
    }

    /**
     * 获得一个由blog所有作者的信息组成的数组
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @access public
     * @return struct
     */
    public function wpGetAuthors($blogId, $userName, $password)
    {
        if (!$this->checkAccess($userName, $password, 'editor')) {
            return ($this->error);
        }

        /** 构建查询*/
        $select = $this->db->select('table.users.uid', 'table.users.name', 'table.users.screenName')->from('table.users');
        $authors = $this->db->fetchAll($select);

        $authorStructs = array();
        foreach ($authors as $author) {
            $authorStructs[] = array(
                'user_id'       => $author['uid'],
                'user_login'    => $author['name'],
                'display_name'  => $author['screenName']
            );
        }

        return $authorStructs;
    }

    /**
     * 添加一个新的分类
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @param struct $category
     * @access public
     * @return void
     */
    public function wpNewCategory($blogId, $userName, $password, $category)
    {
        if (!$this->checkAccess($userName, $password)) {
            return ($this->error);
        }

        /** 开始接受数据 */
        $input['name'] = $category['name'];
        $input['slug'] = Typecho_Common::slugName(empty($category['slug']) ? $category['name'] : $category['slug']);
        $input['parent'] = isset($category['parent_id']) ? $category['parent_id'] :
            (isset($category['parent']) ? $category['parent'] : 0);
        $input['description'] = isset($category['description']) ? $category['description'] : $category['name'];
        $input['do'] = 'insert';

        /** 调用已有组件 */
        try {
            /** 插入 */
             $categoryWidget = $this->singletonWidget('Widget_Metas_Category_Edit', NULL, $input, false);
             $categoryWidget->action();
             return $categoryWidget->mid;
        } catch (Typecho_Widget_Exception $e) {
            return new IXR_Error($e->getCode(), $e->getMessage());
        }

        return new IXR_Error(403, _t('无法添加分类'));
    }

    /**
     * 获取由给定的string开头的链接组成的数组
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @param string $category
     * @param int $max_results
     * @access public
     * @return array
     */
    public function wpSuggestCategories($blogId, $userName, $password, $category, $max_results)
    {
        if (!$this->checkAccess($userName, $password)) {
            return ($this->error);
        }

        $meta = $this->singletonWidget('Widget_Abstract_Metas');

        /** 构造出查询语句并且查询*/
        $key = Typecho_Common::filterSearchQuery($category);
        $key = '%' . $key . '%';
        $select = $meta->select()->where('table.metas.type = ? AND (table.metas.name LIKE ? OR slug LIKE ?)', 'category', $key, $key);

        /** 不要category push到contents的容器中 */
        $categories = $this->db->fetchAll($select);

        /** 初始化categorise数组*/
        $categoryStructs = array();
        foreach ($categories as $category) {
            $categoryStructs[] = array(
                'category_id'   => $category['mid'],
                'category_name' => $category['name'],
            );
        }

        return $categoryStructs;
    }
    
    /**
     * 获取用户
     * 
     * @access public
     * @param string $userName 用户名
     * @param string $password 密码
     * @return array
     */
    public function wpGetUsersBlogs($userName, $password)
    {

        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }

        $struct = array();
        $struct[] = array(
            'isAdmin'   => $this->user->pass('administrator', true),
            'url'       => $this->options->siteUrl,
            'blogid'    => '1',
            'blogName'  => $this->options->title,
            'xmlrpc'    => $this->options->xmlRpcUrl
        );
        return $struct;
    }

        /**
     * 获取用户
     * 
     * @access public
     * @param string $userName 用户名
     * @param string $password 密码
     * @return array
     */
    public function wpGetProfile($blogId, $userName, $password)
    {

        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }

        $struct = array(
            'user_id'       => $this->user->uid,
            'username'      => $this->user->name,
            'first_name'    => '',
            'last_name'     => '',
            'registered'    => new IXR_Date($this->options->timezone +  $this->user->created),
            'bio'           => '',
            'email'         => $this->user->mail,
            'nickname'      => $this->user->screenName,
            'url'           => $this->user->url,
            'display_name'  => $this->user->screenName,
            'roles'         => $this->user->group
        );
        return $struct;
    }
    
    /**
     * 获取标签列表
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @return array
     */
    public function wpGetTags($blogId, $userName, $password)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        
        $struct = array();
        $tags = $this->singletonWidget('Widget_Metas_Tag_Cloud');
        
        while ($tags->next()) {
            $struct[] = array(
                'tag_id'    =>  $tags->mid,
                'name'      =>  $tags->name,
                'count'     =>  $tags->count,
                'slug'      =>  $tags->slug,
                'html_url'  =>  $tags->permalink,
                'rss_url'   =>  $tags->feedUrl
            );
        }
        
        return $struct;
    }
    
    /**
     * 删除分类
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @param integer $categoryId
     * @return array
     */
    public function wpDeleteCategory($blogId, $userName, $password, $categoryId)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password, 'editor')) {
            return $this->error;
        }
        
        try {
            $this->singletonWidget('Widget_Metas_Category_Edit', NULL, 'do=delete&mid=' . intval($categoryId), false);
            return true;
        } catch (Typecho_Exception $e) {
            return false;
        }
    }
    
    /**
     * 获取评论数目
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @param integer $postId
     * @return array
     */
    public function wpGetCommentCount($blogId, $userName, $password, $postId)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        
        $stat = $this->singletonWidget('Widget_Stat', NULL, 'cid=' . intval($postId), false);
        
        return array(
            'approved' => $stat->currentPublishedCommentsNum,
            'awaiting_moderation' => $stat->currentWaitingCommentsNum,
            'spam' => $stat->currentSpamCommentsNum,
            'total_comments' => $stat->currentCommentsNum
        );
    }

    
    /**
     * 获取文章类型列表
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @return array
     */
    public function wpGetPostFormats($blogId, $userName, $password)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        
        return array(
            'standard' => _t('标准')
        );
    }
    
    /**
     * 获取文章状态列表
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @return array
     */
    public function wpGetPostStatusList($blogId, $userName, $password)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        
        return array(
            'draft'     =>  _t('草稿'),
            'pending'   =>  _t('待审核'),
            'publish'   =>  _t('已发布')
        );
    }
    
    /**
     * 获取页面状态列表
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @return array
     */
    public function wpGetPageStatusList($blogId, $userName, $password)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password, 'editor')) {
            return $this->error;
        }
        
        return array(
            'draft'     =>  _t('草稿'),
            'publish'   =>  _t('已发布')
        );
    }


    
    /**
     * 获取评论状态列表
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @return array
     */
    public function wpGetCommentStatusList($blogId, $userName, $password)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        
        return array(
            'hold'      =>  _t('待审核'),
            'approve'   =>  _t('显示'),
            'spam'      =>  _t('垃圾')
        );
    }
    
    /**
     * 获取页面模板
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @return array
     */
    public function wpGetPageTemplates($blogId, $userName, $password)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password, 'editor')) {
            return $this->error;
        }
        
        $templates = array_flip($this->getTemplates());
        $templates['Default'] = '';
        
        return $templates;
    }
    
    /**
     * 获取系统选项
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @param array $options
     * @return array
     */
    public function wpGetOptions($blogId, $userName, $password, $options = array())
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password, 'administrator')) {
            return $this->error;
        }
        
        $struct = array();
        if (empty($options)) {
            $options = array_keys($this->_wpOptions);
        }
        
        foreach ($options as $option) {
            if (isset($this->_wpOptions[$option])) {
                $struct[$option] = $this->_wpOptions[$option];
                if (isset($struct[$option]['option'])) {
                    $struct[$option]['value'] = $this->options->{$struct[$option]['option']};
                    unset($struct[$option]['option']);
                }
            }
        }
        
        return $struct;
    }
    
    /**
     * 设置系统选项
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @param array $options
     * @return array
     */
    public function wpSetOptions($blogId, $userName, $password, $options = array())
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password, 'administrator')) {
            return $this->error;
        }
        
        $struct = array();
        foreach ($options as $option => $value) {
            if (isset($this->_wpOptions[$option])) {
                $struct[$option] = $this->_wpOptions[$option];
                if (isset($struct[$option]['option'])) {
                    $struct[$option]['value'] = $this->options->{$struct[$option]['option']};
                    unset($struct[$option]['option']);
                }
            
                if (!$this->_wpOptions[$option]['readonly'] && isset($this->_wpOptions[$option]['option'])) {
                    if ($this->db->query($this->db->update('table.options')
                    ->rows(array('value' => $value))
                    ->where('name = ?', $this->_wpOptions[$option]['option'])) > 0) {
                        $struct[$option]['value'] = $value;
                    }
                }
            }
        }
        
        return $struct;
    }
    
    /**
     * 获取评论
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @param integer $commentId
     * @return array
     */
    public function wpGetComment($blogId, $userName, $password, $commentId)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        
        $comment = $this->singletonWidget('Widget_Comments_Edit', NULL, 'do=get&coid=' . intval($commentId), false);
        
        if (!$comment->have()) {
            return new IXR_Error(404, _t('评论不存在'));
        }
        
        if (!$comment->commentIsWriteable()) {
            return new IXR_Error(403, _t('没有获取评论的权限'));
        }
        
        return array(
            'date_created_gmt'		=> new IXR_Date($this->options->timezone + $comment->created),
			'user_id'				=> $comment->authorId,
			'comment_id'			=> $comment->coid,
			'parent'				=> $comment->parent,
			'status'				=> $this->typechoToWordpressStatus($comment->status, 'comment'),
			'content'				=> $comment->text,
			'link'					=> $comment->permalink,
			'post_id'				=> $comment->cid,
			'post_title'			=> $comment->title,
			'author'				=> $comment->author,
			'author_url'			=> $comment->url,
			'author_email'			=> $comment->mail,
			'author_ip'				=> $comment->ip,
			'type'					=> $comment->type
        );
    }
    
    /**
     * 获取评论列表
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @param array $struct
     * @return array
     */
    public function wpGetComments($blogId, $userName, $password, $struct)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        
        $input = array();
        if (!empty($struct['status'])) {
            $input['status'] = 'hold' == $input['status'] ? $input['status'] : 
                $this->wordpressToTypechoStatus($struct['status']);
        } else {
            $input['__typecho_all_comments'] = 'on';
        }
        
        if (!empty($struct['post_id'])) {
            $input['cid'] = $struct['post_id'];
        }
        
        $pageSize = 10;
        if (!empty($struct['number'])) {
            $pageSize = abs(intval($struct['number']));
        }
        
        if (!empty($struct['offset'])) {
            $offset = abs(intval($struct['offset']));
            $input['page'] = ceil($offset / $pageSize);
        }
        
        $comments = $this->singletonWidget('Widget_Comments_Admin', 'pageSize=' . $pageSize, $input, false);
        $commentsStruct = array();
        
        while ($comments->next()) {
            $commentsStruct[] = array(
                'date_created_gmt'		=> new IXR_Date($this->options->timezone + $comments->created),
                'user_id'				=> $comments->authorId,
                'comment_id'			=> $comments->coid,
                'parent'				=> $comments->parent,
                'status'				=> $this->typechoToWordpressStatus($comments->status, 'comment'),
                'content'				=> $comments->text,
                'link'					=> $comments->permalink,
                'post_id'				=> $comments->cid,
                'post_title'			=> $comments->title,
                'author'				=> $comments->author,
                'author_url'			=> $comments->url,
                'author_email'			=> $comments->mail,
                'author_ip'				=> $comments->ip,
                'type'					=> $comments->type
            );
        }
        
        return $commentsStruct;
    }
    
    /**
     * 获取评论
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @param integer $commentId
     * @return boolean
     */
    public function wpDeleteComment($blogId, $userName, $password, $commentId)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        
        $commentId = abs(intval($commentId));
        $commentWidget = $this->singletonWidget('Widget_Abstract_Comments');
        $where = $this->db->sql()->where('coid = ?', $commentId);
        
        if (!$commentWidget->commentIsWriteable($where)) {
            return new IXR_Error(403, _t('无法编辑此评论'));
        }

        return intval($this->singletonWidget('Widget_Abstract_Comments')->delete($where)) > 0;
    }
    
    /**
     * 编辑评论
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @param integer $commentId
     * @param array $struct
     * @return boolean
     */
    public function wpEditComment($blogId, $userName, $password, $commentId, $struct)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        
        $commentId = abs(intval($commentId));
        $commentWidget = $this->singletonWidget('Widget_Abstract_Comments');
        $where = $this->db->sql()->where('coid = ?', $commentId);
        
        if (!$commentWidget->commentIsWriteable($where)) {
            return new IXR_Error(403, _t('无法编辑此评论'));
        }
        
        $input = array();
        
        if (isset($struct['date_created_gmt'])) {
            $input['created'] = $struct['date_created_gmt']->getTimestamp() - $this->options->timezone + $this->options->serverTimezone;
        }
        
        if (isset($struct['status'])) {
            $input['status'] = $this->wordpressToTypechoStatus($struct['status'], 'comment');
        }
        
        if (isset($struct['content'])) {
            $input['text'] = $struct['content'];
        }
        
        if (isset($struct['author'])) {
            $input['author'] = $struct['author'];
        }
        
        if (isset($struct['author_url'])) {
            $input['url'] = $struct['author_url'];
        }
        
        if (isset($struct['author_email'])) {
            $input['mail'] = $struct['author_email'];
        }
        
        $result = $commentWidget->update((array) $input, $where);
        
        if (!$result) {
            return new IXR_Error(404, _t('评论不存在'));
        }
        
        return true;
    }
    
    /**
     * 更新评论
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @param mixed $path
     * @param array $struct
     * @return int
     */
    public function wpNewComment($blogId, $userName, $password, $path, $struct)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        
        if (is_numeric($path)) {
            $post = $this->singletonWidget('Widget_Archive', 'type=single', 'cid=' . $path, false);
        } else {
            /** 检查目标地址是否正确*/
            $pathInfo = Typecho_Common::url(substr($path, strlen($this->options->index)), '/');
            $post = Typecho_Router::match($pathInfo);
        }
        
        /** 这样可以得到cid或者slug*/
        if (!isset($post) || !($post instanceof Widget_Archive) || !$post->have() || !$post->is('single')) {
            return new IXR_Error(404, _t('这个目标地址不存在'));
        }
        
        $input = array();
        $input['permalink'] = $post->pathinfo;
        $input['type']  = 'comment';
        
        if (isset($struct['comment_author'])) {
            $input['author'] = $struct['author'];
        }
        
        if (isset($struct['comment_author_email'])) {
            $input['mail'] = $struct['author_email'];
        }
        
        if (isset($struct['comment_author_url'])) {
            $input['url'] = $struct['author_url'];
        }
        
        if (isset($struct['comment_parent'])) {
            $input['parent'] = $struct['comment_parent'];
        }
        
        if (isset($struct['content'])) {
            $input['text'] = $struct['content'];
        }
        
        try {
            $commentWidget =  $this->singletonWidget('Widget_Feedback', 'checkReferer=false', $input, false);
            $commentWidget->action();
            return intval($commentWidget->coid);
        } catch (Typecho_Exception $e) {
            return new IXR_Error(500, $e->getMessage());
        }
        
        return new IXR_Error(403, _t('无法添加评论'));
    }



    /**
     * 获取媒体文件
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @param struct $struct
     * @return boolean
     */
    public function wpGetMediaLibrary($blogId, $userName, $password, $struct)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        

        $input = array();

        if (!empty($struct['parent_id'])) {
            $input['parent'] = $struct['parent_id'];
        }

        if (!empty($struct['mime_type'])) {
            $input['mime'] = $struct['mime_type'];
        }
        
        $pageSize = 10;
        if (!empty($struct['number'])) {
            $pageSize = abs(intval($struct['number']));
        }
        
        if (!empty($struct['offset'])) {
            $input['page'] = abs(intval($struct['offset'])) + 1;
        }
        
        $attachments = $this->singletonWidget('Widget_Contents_Attachment_Admin', 'pageSize=' . $pageSize, $input, false);
        $attachmentsStruct = array();
        
        while ($attachments->next()) {
            $attachmentsStruct[] = array(
                'attachment_id'         => $attachments->cid,
                'date_created_gmt'      => new IXR_Date($this->options->timezone + $attachments->created),
                'parent'                => $attachments->parent,
                'link'                  => $attachments->attachment->url,
                'title'                 => $attachments->title,
                'caption'               => $attachments->slug,
                'description'           => $attachments->attachment->description,
                'metadata'              => array(
                    'file'  =>  $attachments->attachment->path,
                    'size'  =>  $attachments->attachment->size,
                ),
                'thumbnail'             => $attachments->attachment->url,

            );
        }
        return $attachmentsStruct;
    }

    /**
     * 获取媒体文件
     * 
     * @access public
     * @param integer $blogId
     * @param string $userName
     * @param string $password
     * @param int $attachmentId
     * @return boolean
     */
    public function wpGetMediaItem($blogId, $userName, $password, $attachmentId)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        
        
        $attachment = $this->singletonWidget('Widget_Contents_Attachment_Edit', NULL, "cid={$attachmentId}");
        $struct = array(
            'attachment_id'         => $attachment->cid,
            'date_created_gmt'      => new IXR_Date($this->options->timezone + $attachment->created),
            'parent'                => $attachment->parent,
            'link'                  => $attachment->attachment->url,
            'title'                 => $attachment->title,
            'caption'               => $attachment->slug,
            'description'           => $attachment->attachment->description,
            'metadata'              => array(
                'file'  =>  $attachment->attachment->path,
                'size'  =>  $attachment->attachment->size,
            ),
            'thumbnail'             => $attachment->attachment->url,

        );
        return $struct;
    }



    /**
     * MetaWeblog API
     * about MetaWeblog API, you can see http://www.xmlrpc.com/metaWeblogApi
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @param mixed $content
     * @param bool $publish
     * @access public
     * @return int
     */
    public function mwNewPost($blogId, $userName, $password, $content, $publish)
    {
        /** 检查权限*/
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }

        /** 取得content内容 */
        $input = array();
        $type = isset($content['post_type']) && 'page' == $content['post_type'] ? 'page' : 'post';
        
        $input['title'] = trim($content['title']) == NULL ? _t('未命名文档') : $content['title'];

        if (isset($content['slug'])) {
            $input['slug'] = $content['slug'];
        } else if (isset($content['wp_slug'])) {
            //fix issue 338, wlw只发送这个
            $input['slug'] = $content['wp_slug'];
        }

        $input['text'] = !empty($content['mt_text_more']) ? $content['description'] 
            . "\n<!--more-->\n" . $content['mt_text_more'] : $content['description'];
        $input['text'] = $this->pluginHandle()->textFilter($input['text'], $this); 
        
        $input['password'] = isset($content["wp_password"]) ? $content["wp_password"] : NULL;
        $input['order'] = isset($content["wp_page_order"]) ? $content["wp_page_order"] : NULL;

        $input['tags'] = isset($content['mt_keywords']) ? $content['mt_keywords'] : NULL;
        $input['category'] = array();

        if (isset($content['postId'])) {
            $input['cid'] = $content['postId'];
        }
        
        if ('page' == $type && isset($content['wp_page_template'])) {
            $input['template'] = $content['wp_page_template'];
        }

        if (isset($content['dateCreated'])) {
            /** 解决客户端与服务器端时间偏移 */
            $input['created'] = $content['dateCreated']->getTimestamp() - $this->options->timezone + $this->options->serverTimezone;
        }

        if (!empty($content['categories']) && is_array($content['categories'])) {
            foreach ($content['categories'] as $category) {
                if (!$this->db->fetchRow($this->db->select('mid')
                ->from('table.metas')->where('type = ? AND name = ?', 'category', $category))) {
                    $result = $this->wpNewCategory($blogId, $userName, $password, array('name' => $category));
                    if (true !== $result) {
                        return $result;
                    }
                }

                $input['category'][] = $this->db->fetchObject($this->db->select('mid')
                ->from('table.metas')->where('type = ? AND name = ?', 'category', $category)
                ->limit(1))->mid;
            }
        }

        $input['allowComment'] = (isset($content['mt_allow_comments']) && (1 == $content['mt_allow_comments']
        || 'open' == $content['mt_allow_comments'])) ? 1 : ((isset($content['mt_allow_comments']) && (0 == $content['mt_allow_comments']
        || 'closed' == $content['mt_allow_comments'])) ? 0 : $this->options->defaultAllowComment);

        $input['allowPing'] = (isset($content['mt_allow_pings']) && (1 == $content['mt_allow_pings']
        || 'open' == $content['mt_allow_pings'])) ? 1 : ((isset($content['mt_allow_pings']) && (0 == $content['mt_allow_pings']
        || 'closed' == $content['mt_allow_pings'])) ? 0 : $this->options->defaultAllowPing);

        $input['allowFeed'] = $this->options->defaultAllowFeed;
        $input['do'] = $publish ? 'publish' : 'save';
        $input['markdown'] = $this->options->xmlrpcMarkdown;
        
        /** 调整状态 */
        if (isset($content["{$type}_status"])) {
            $status = $this->wordpressToTypechoStatus($content["{$type}_status"], $type);
            
            if ('publish' == $status || 'waiting' == $status || 'private' == $status) {
                $input['do'] = 'publish';
                
                if ('private' == $status) {
                    $input['private'] = 1;
                }
            } else {
                $input['do'] = 'save';
            }
        }

        /** 对未归档附件进行归档 */
        $unattached = $this->db->fetchAll($this->select()->where('table.contents.type = ? AND
        (table.contents.parent = 0 OR table.contents.parent IS NULL)', 'attachment'), array($this, 'filter'));

        if (!empty($unattached)) {
            foreach ($unattached as $attach) {
                if (false !== strpos($input['text'], $attach['attachment']->url)) {
                    if (!isset($input['attachment'])) {
                        $input['attachment'] = array();
                    }

                    $input['attachment'][] = $attach['cid'];
                }
            }
        }

        /** 调用已有组件 */
        try {
            /** 插入 */
            if ('page' == $type) {
                $this->singletonWidget('Widget_Contents_Page_Edit', NULL, $input, false)->action();
            } else {
                $this->singletonWidget('Widget_Contents_Post_Edit', NULL, $input, false)->action();
            }
        
            return $this->singletonWidget('Widget_Notice')->getHighlightId();
        } catch (Typecho_Widget_Exception $e) {
            return new IXR_Error($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 编辑post
     *
     * @param int $postId
     * @param string $userName
     * @param string $password
     * @param struct $content
     * @param bool $publish
     * @access public
     * @return int
     */
    public function mwEditPost($postId, $userName, $password, $content, $publish = true)
    {
        $content['postId'] = $postId;
        return $this->mwNewPost(1, $userName, $password, $content, $publish);
    }

    /**
     * 获取指定id的post
     *
     * @param int $postId
     * @param string $userName
     * @param string $password
     * @access public
     * @return void
     */
    public function mwGetPost($postId, $userName, $password)
    {
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }

        try {
            $post = $this->singletonWidget('Widget_Contents_Post_Edit', NULL, "cid={$postId}");
        } catch (Typecho_Widget_Exception $e) {
            return new IXR_Error($e->getCode(), $e->getMessage());
        }

        /** 对文章内容做截取处理，以获得description和text_more*/
        list($excerpt, $more) = $this->getPostExtended($post);
        /** 只需要分类的name*/
        $categories = Typecho_Common::arrayFlatten($post->categories, 'name');
        $tags = Typecho_Common::arrayFlatten($post->tags, 'name');

        $postStruct = array(
                'dateCreated'   => new IXR_Date($this->options->timezone + $post->created),
                'userid'        => $post->authorId,
                'postid'       => $post->cid,
                'description'   => $excerpt,
                'title'         => $post->title,
                'link'          => $post->permalink,
                'permaLink'     => $post->permalink,
                'categories'    => $categories,
                'mt_excerpt'    => $post->description,
                'mt_text_more'  => $more,
                'mt_allow_comments' => intval($post->allowComment),
                'mt_allow_pings'    => intval($post->allowPing),
                'mt_keywords'	=> implode(', ', $tags),
                'wp_slug'       => $post->slug,
                'wp_password'   => $post->password,
                'wp_author'     => $post->author->name,
                'wp_author_id'  => $post->authorId,
                'wp_author_display_name' => $post->author->screenName,
                'date_created_gmt'  =>  new IXR_Date($post->created),
                'post_status'   => $this->typechoToWordpressStatus($post->status, 'post'),
                'custom_fields' => array(),
                'sticky'        => 0
        );
        
        return $postStruct;
    }

    /**
     * 获取前$postsNum个post
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @param int $postsNum
     * @access public
     * @return postStructs
     */
    public function mwGetRecentPosts($blogId, $userName, $password, $postsNum)
    {
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }

        $posts = $this->singletonWidget('Widget_Contents_Post_Admin', "pageSize={$postsNum}", 'status=all');

        $postStructs = array();
        /** 如果这个post存在则输出，否则输出错误 */
        while ($posts->next()) {
            /** 对文章内容做截取处理，以获得description和text_more*/
            list($excerpt, $more) = $this->getPostExtended($posts);

            /** 只需要分类的name*/
            /** 可以用flatten函数处理 */
            $categories = Typecho_Common::arrayFlatten($posts->categories, 'name');
            $tags = Typecho_Common::arrayFlatten($posts->tags, 'name');

            $postStructs[] = array(
                    'dateCreated'            => new IXR_Date($this->options->timezone + $posts->created),
                    'userid'                 => $posts->authorId,
                    'postid'                 => $posts->cid,
                    'description'            => $excerpt,
                    'title'                  => $posts->title,
                    'link'                   => $posts->permalink,
                    'permaLink'              => $posts->permalink,
                    'categories'             => $categories,
                    'mt_excerpt'             => $posts->description,
                    'mt_text_more'           => $more,
                    'wp_more_text'           => $more,
                    'mt_allow_comments'      => intval($posts->allowComment),
                    'mt_allow_pings'         => intval($posts->allowPing),
                    'mt_keywords'	         => implode(', ', $tags),
                    'wp_slug'                => $posts->slug,
                    'wp_password'            => $posts->password,
                    'wp_author'              => $posts->author->name,
                    'wp_author_id'           => $posts->authorId,
                    'wp_author_display_name' => $posts->author->screenName,
                    'date_created_gmt'       => new IXR_Date($posts->created),
                    'post_status'            => $this->typechoToWordpressStatus($posts->status, 'post'),
                    'custom_fields'          => array(),
                    'wp_post_format'         => 'standard',
                    'date_modified'          => new IXR_Date($this->options->timezone + $posts->modified),
                    'date_modified_gmt'      => new IXR_Date($posts->modified),
                    'wp_post_thumbnail'      => '',
                    'sticky'                 => 0
            );
        }

        return $postStructs;
    }

    /**
     * 获取所有的分类
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @access public
     * @return categoryStructs
     */
    public function mwGetCategories($blogId, $userName, $password)
    {
        if (!$this->checkAccess($userName, $password)) {
            return ($this->error);
        }

        $categories = $this->singletonWidget('Widget_Metas_Category_List');

        /** 初始化category数组*/
        $categoryStructs = array();
        while ($categories->next()) {
            $categoryStructs[] = array(
                'categoryId'            => $categories->mid,
                'parentId'              => $categories->parent,
                'categoryName'          => $categories->name,
                'categoryDescription'   => $categories->description,
                'description'           => $categories->name,
                'htmlUrl'               => $categories->permalink,
                'rssUrl'                => $categories->feedUrl,
            );
        }

        return $categoryStructs;
    }

    /**
     * mwNewMediaObject
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @param mixed $data
     * @access public
     * @return void
     */
    public function mwNewMediaObject($blogId, $userName, $password, $data)
    {
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }

        $result = Widget_Upload::uploadHandle($data);

        if (false === $result) {
            return IXR_Error(500, _t('上传失败'));
        } else {

            $insertId = $this->insert(array(
                'title'     =>  $result['name'],
                'slug'      =>  $result['name'],
                'type'      =>  'attachment',
                'status'    =>  'publish',
                'text'      =>  serialize($result),
                'allowComment'      =>  1,
                'allowPing'         =>  0,
                'allowFeed'         =>  1
            ));

            $this->db->fetchRow($this->select()->where('table.contents.cid = ?', $insertId)
                    ->where('table.contents.type = ?', 'attachment'), array($this, 'push'));

            /** 增加插件接口 */
            $this->pluginHandle()->upload($this);

            return array(
                'file' => $this->attachment->name,
                'url'  => $this->attachment->url
            );
        }
    }

    /**
     * 获取 $postNum个post title
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @param int $postNum
     * @access public
     * @return postTitleStructs
     */
    public function mtGetRecentPostTitles($blogId, $userName, $password, $postsNum)
    {
        if (!$this->checkAccess($userName, $password)) {
            return ($this->error);
        }

        /** 读取数据*/
        $posts = $this->singletonWidget('Widget_Contents_Post_Admin', "pageSize=$postsNum", 'status=all');

        /**初始化*/
        $postTitleStructs = array();
        while ($posts->next()) {
            $postTitleStructs[] = array(
                'dateCreated'       => new IXR_Date($this->options->timezone + $posts->created),
                'userid'            => $posts->authorId,
                'postid'            => $posts->cid,
                'title'             => $posts->title,
                'date_created_gmt'  => new IXR_Date($this->options->timezone + $posts->created)
            );
        }

        return $postTitleStructs;
    }

    /**
     * 获取分类列表
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @access public
     * @return categories
     */
    public function mtGetCategoryList($blogId, $userName, $password)
    {
        if (!$this->checkAccess($userName, $password)) {
            return ($this->error);
        }

        $categories = $this->singletonWidget('Widget_Metas_Category_List');

        /** 初始化categorise数组*/
        $categoryStructs = array();
        while ($categories->next()) {
            $categoryStructs[] = array(
                'categoryId'   => $categories->mid,
                'categoryName' => $categories->name,
            );
        }
        return $categoryStructs;
    }

    /**
     * 获取指定post的分类
     *
     * @param int $postId
     * @param string $userName
     * @param string $password
     * @access public
     * @return void
     */
    public function mtGetPostCategories($postId, $userName, $password)
    {
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }

        try {
            $post = $this->singletonWidget('Widget_Contents_Post_Edit', NULL, "cid={$postId}");
        } catch (Typecho_Widget_Exception $e) {
            return new IXR_Error($e->getCode(), $e->getMessage());
        }

        /** 格式化categories*/
        $categories = array();
        foreach ($post->categories as $category) {
            $categories[] = array(
                'categoryName'      => $category['name'],
                'categoryId'        => $category['mid'],
                'isPrimary'         => true
            );
        }
        return $categories;
    }

    /**
     * 修改post的分类
     *
     * @param int $postId
     * @param string $userName
     * @param string $password
     * @param string $categories
     * @access public
     * @return bool
     */
    public function mtSetPostCategories($postId, $userName, $password, $categories)
    {
        if (!$this->checkAccess($userName, $password, 'editor')) {
            return $this->error;
        }

        try {
            $post = $this->singletonWidget('Widget_Contents_Post_Edit', NULL, "cid={$postId}");
        } catch (Typecho_Widget_Exception $e) {
            return new IXR_Error($e->getCode(), $e->getMessage());
        }

        $post->setCategories($postId, Typecho_Common::arrayFlatten($categories, 'categoryId'),
        'publish' == $post->status);
        return true;
    }

    /**
     * 发布(重建)数据
     *
     * @param int $postId
     * @param string $userName
     * @param string $password
     * @access public
     * @return bool
     */
    public function mtPublishPost($postId, $userName, $password)
    {
        if (!$this->checkAccess($userName, $password, 'editor')) {
            return $this->error;
        }

        /** 过滤id为$postId的post */
        $select = $this->select()->where('table.contents.cid = ? AND table.contents.type = ?', $postId, 'post')->limit(1);

        /** 提交查询 */
        $post = $this->db->fetchRow($select, array($this, 'push'));
        if ($this->authorId != $this->user->uid && !$this->checkAccess($userName, $password, 'administrator')) {
            return new IXR_Error(403, '权限不足.');
        }

        /** 暂时只做成发布*/
        $content = array();
        $this->update($content, $this->db->sql()->where('table.contents.cid = ?', $postId));


    }

    /**
     * 取得当前用户的所有blog
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @access public
     * @return void
     */
    public function bloggerGetUsersBlogs($blogId, $userName, $password)
    {
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }

        $struct = array();
        $struct[] = array(
            'isAdmin'  => $this->user->pass('administrator', true),
            'url'	  => $this->options->siteUrl,
            'blogid'   => '1',
            'blogName' => $this->options->title,
            'xmlrpc'   => $this->options->xmlRpcUrl
        );
        
        return $struct;
    }

    /**
     * 返回当前用户的信息
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @access public
     * @return void
     */
    public function bloggerGetUserInfo($blogId, $userName, $password)
    {
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }

        $struct = array(
            'nickname'  => $this->user->screenName,
            'userid'    => $this->user->uid,
            'url'       => $this->user->url,
            'email'     => $this->user->mail,
            'lastname'  => '',
            'firstname' => ''
        );
        
        return $struct;
    }

    /**
     * 获取当前作者的一个指定id的post的详细信息
     *
     * @param int $blogId
     * @param int $postId
     * @param string $userName
     * @param string $password
     * @access public
     * @return void
     */
    public function bloggerGetPost($blogId, $postId, $userName, $password)
    {
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }

        try {
            $post = $this->singletonWidget('Widget_Contents_Post_Edit', NULL, "cid={$postId}");
        } catch (Typecho_Widget_Exception $e) {
            return new IXR_Error($e->getCode(), $e->getMessage());
        }
        
        $categories = Typecho_Common::arrayFlatten($post->categories, 'name');

        $content = '<title>' . $post->title . '</title>';
        $content .= '<category>' . implode(',', $categories) . '</category>';
        $content .= stripslashes($post->text);

        $struct = array(
            'userid'        => $post->authorId,
            'dateCreated'   => new IXR_Date($this->options->timezone + $post->created),
            'content'       => $content,
            'postid'        => $post->cid
        );
        return $struct;
    }

    /**
     * bloggerDeletePost
     * 删除文章
     * @param mixed $blogId
     * @param mixed $userName
     * @param mixed $password
     * @param mixed $publish
     * @access public
     * @return bool
     */
    public function bloggerDeletePost($blogId, $postId, $userName, $password, $publish)
    {
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        try {
            $this->singletonWidget('Widget_Contents_Post_Edit', NULL, "cid={$postId}", false)->deletePost();
        } catch (Typecho_Widget_Exception $e) {
            return new IXR_Error($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 获取当前作者前postsNum个post
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @param int $postsNum
     * @access public
     * @return void
     */
    public function bloggerGetRecentPosts($blogId, $userName, $password, $postsNum)
    {
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        //todo:限制数量
        $posts = $this->singletonWidget('Widget_Contents_Post_Admin', "pageSize=$postsNum", 'status=all');

        $postStructs = array();
        while ($posts->next()) {
            $categories = Typecho_Common::arrayFlatten($posts->categories, 'name');
            
            $content = '<title>' . $posts->title . '</title>';
            $content .= '<category>' . implode(',', $categories) . '</category>';
            $content .= stripslashes($posts->text);

            $struct = array(
                'userid'        => $posts->authorId,
                'dateCreated'   => new IXR_Date($this->options->timezone + $posts->created),
                'content'       => $content,
                'postid'        => $posts->cid,
            );
            $postStructs[] = $struct;
        }
        if (NULL == $postStructs) {
            return new IXR_Error('404', '没有任何文章');
        }
        return $postStructs;
    }

    /**
     * bloggerGetTemplate
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @param mixed $template
     * @access public
     * @return void
     */
    public function bloggerGetTemplate($blogId, $userName, $password, $template)
    {
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        /** todo:暂时先返回true*/
        return true;
    }

    /**
     * bloggerSetTemplate
     *
     * @param int $blogId
     * @param string $userName
     * @param string $password
     * @param mixed $content
     * @param mixed $template
     * @access public
     * @return void
     */
    public function bloggerSetTemplate($blogId, $userName, $password, $content, $template)
    {
        if (!$this->checkAccess($userName, $password)) {
            return $this->error;
        }
        /** todo:暂时先返回true*/
        return true;
    }

    /**
     * pingbackPing
     *
     * @param string $source
     * @param string $target
     * @access public
     * @return void
     */
    public function pingbackPing($source, $target)
    {
        /** 检查目标地址是否正确*/
        $pathInfo = Typecho_Common::url(substr($target, strlen($this->options->index)), '/');
        $post = Typecho_Router::match($pathInfo);

        /** 这样可以得到cid或者slug*/
        if (!($post instanceof Widget_Archive) || !$post->have() || !$post->is('single')) {
            return new IXR_Error(33, _t('这个目标地址不存在'));
        }

        if ($post) {
            /** 检查是否可以ping*/
            if ($post->allowPing) {

                /** 现在可以ping了，但是还得检查下这个pingback是否已经存在了*/
                $pingNum = $this->db->fetchObject($this->db->select(array('COUNT(coid)' => 'num'))
                ->from('table.comments')->where('table.comments.cid = ? AND table.comments.url = ? AND table.comments.type <> ?',
                $post->cid, $source, 'comment'))->num;

                if ($pingNum <= 0) {
                    /** 检查源地址是否存在*/
                    if (!($http = Typecho_Http_Client::get())) {
                        return new IXR_Error(16, _t('源地址服务器错误'));
                    }

                    try {

                        $http->setTimeout(5)->send($source);
                        $response = $http->getResponseBody();

                        if (200 == $http->getResponseStatus()) {

                            if (!$http->getResponseHeader('x-pingback')) {
                                preg_match_all("/<link[^>]*rel=[\"']([^\"']*)[\"'][^>]*href=[\"']([^\"']*)[\"'][^>]*>/i", $response, $out);
                                if (!isset($out[1]['pingback'])) {
                                    return new IXR_Error(50, _t('源地址不支持PingBack'));
                                }
                            }

                        } else {
                            return new IXR_Error(16, _t('源地址服务器错误'));
                        }

                    } catch (Exception $e) {
                        return new IXR_Error(16, _t('源地址服务器错误'));
                    }

                    /** 现在开始插入以及邮件提示了 $response就是第一行请求时返回的数组*/
                    preg_match("/\<title\>([^<]*?)\<\/title\\>/is", $response, $matchTitle);
                    $finalTitle = Typecho_Common::removeXSS(trim(strip_tags($matchTitle[1])));

                    /** 干掉html tag，只留下<a>*/
                    $text = Typecho_Common::stripTags($response, '<a href="">');

                    /** 此处将$target quote,留着后面用*/
                    $pregLink = preg_quote($target);

                    /** 找出含有target链接的最长的一行作为$finalText*/
                    $finalText = '';
                    $lines = explode("\n", $text);

                    foreach ($lines as $line) {
                        $line = trim($line);
                        if (NULL != $line) {
                            if (preg_match("|<a[^>]*href=[\"']{$pregLink}[\"'][^>]*>(.*?)</a>|",$line)) {
                                if (strlen($line) > strlen($finalText)) {
                                    /** <a>也要干掉，*/
                                    $finalText = Typecho_Common::stripTags($line);
                                }
                            }
                        }
                    }

                    /** 截取一段字*/
                    if (NULL == trim($finalText)) {
                        return new IXR_Error('17', _t('源地址中不包括目标地址'));
                    }

                    $finalText = '[...]' . Typecho_Common::subStr($finalText, 0, 200, '') . '[...]';

                    $pingback = array(
                        'cid'       =>  $post->cid,
                        'created'   =>  $this->options->gmtTime,
                        'agent'     =>  $this->request->getAgent(),
                        'ip'        =>  $this->request->getIp(),
                        'author'    =>  $finalTitle,
                        'url'       =>  Typecho_Common::safeUrl($source),
                        'text'      =>  $finalText,
                        'ownerId'   =>  $post->author->uid,
                        'type'      =>  'pingback',
                        'status'    =>  $this->options->commentsRequireModeration ? 'waiting' : 'approved'
                    );

                    /** 加入plugin */
                    $pingback = $this->pluginHandle()->pingback($pingback, $post);

                    /** 执行插入*/
                    $insertId = $this->singletonWidget('Widget_Abstract_Comments')->insert($pingback);

                    /** 评论完成接口 */
                    $this->pluginHandle()->finishPingback($this);

                    return $insertId;

                    /** todo:发送邮件提示*/
                } else {
                    return new IXR_Error(48, _t('PingBack已经存在'));
                }
            } else {
                return IXR_Error(49, _t('目标地址禁止Ping'));
            }
        } else {
            return new IXR_Error(33, _t('这个目标地址不存在'));
        }
    }
    
    /**
     * 回收变量
     * 
     * @access public
     * @param string $methodName 方法
     * @return void
     */
    public function hookAfterCall($methodName)
    {
        if (!empty($this->_usedWidgetNameList)) {
            foreach ($this->_usedWidgetNameList as $key => $widgetName) {
                $this->destory($widgetName);
                unset($this->_usedWidgetNameList[$key]);
            }
        }
    }

    /**
     * 入口执行方法
     *
     * @access public
     * @return void
     */
    public function action()
    {
        if (isset($this->request->rsd)) {
            echo
<<<EOF
<?xml version="1.0" encoding="{$this->options->charset}"?>
<rsd version="1.0" xmlns="http://archipelago.phrasewise.com/rsd">
    <service>
        <engineName>Typecho</engineName>
        <engineLink>http://www.typecho.org/</engineLink>
        <homePageLink>{$this->options->siteUrl}</homePageLink>
        <apis>
            <api name="WordPress" blogID="1" preferred="true" apiLink="{$this->options->xmlRpcUrl}" />
            <api name="Movable Type" blogID="1" preferred="false" apiLink="{$this->options->xmlRpcUrl}" />
            <api name="MetaWeblog" blogID="1" preferred="false" apiLink="{$this->options->xmlRpcUrl}" />
            <api name="Blogger" blogID="1" preferred="false" apiLink="{$this->options->xmlRpcUrl}" />
        </apis>
    </service>
</rsd>
EOF;
        } else if (isset($this->request->wlw)) {
            echo
<<<EOF
<?xml version="1.0" encoding="{$this->options->charset}"?>
<manifest xmlns="http://schemas.microsoft.com/wlw/manifest/weblog">
    <options>
        <supportsKeywords>Yes</supportsKeywords>
        <supportsFileUpload>Yes</supportsFileUpload>
        <supportsExtendedEntries>Yes</supportsExtendedEntries>
        <supportsCustomDate>Yes</supportsCustomDate>
        <supportsCategories>Yes</supportsCategories>

        <supportsCategoriesInline>Yes</supportsCategoriesInline>
        <supportsMultipleCategories>Yes</supportsMultipleCategories>
        <supportsHierarchicalCategories>Yes</supportsHierarchicalCategories>
        <supportsNewCategories>Yes</supportsNewCategories>
        <supportsNewCategoriesInline>Yes</supportsNewCategoriesInline>
        <supportsCommentPolicy>Yes</supportsCommentPolicy>

        <supportsPingPolicy>Yes</supportsPingPolicy>
        <supportsAuthor>Yes</supportsAuthor>
        <supportsSlug>Yes</supportsSlug>
        <supportsPassword>Yes</supportsPassword>
        <supportsExcerpt>Yes</supportsExcerpt>
        <supportsTrackbacks>Yes</supportsTrackbacks>

        <supportsPostAsDraft>Yes</supportsPostAsDraft>

        <supportsPages>Yes</supportsPages>
        <supportsPageParent>No</supportsPageParent>
        <supportsPageOrder>Yes</supportsPageOrder>
        <requiresXHTML>True</requiresXHTML>
        <supportsAutoUpdate>No</supportsAutoUpdate>

    </options>
</manifest>
EOF;
        } else {



            /** 直接把初始化放到这里 */
            new IXR_Server(array(
                /** WordPress API */
                'wp.getPage'                => array($this, 'wpGetPage'),
                'wp.getPages'               => array($this, 'wpGetPages'),
                'wp.newPage'                => array($this, 'wpNewPage'),
                'wp.deletePage'             => array($this, 'wpDeletePage'),
                'wp.editPage'               => array($this, 'wpEditPage'),
                'wp.getPageList'            => array($this, 'wpGetPageList'),
                'wp.getAuthors'             => array($this, 'wpGetAuthors'),
                'wp.getCategories'          => array($this, 'mwGetCategories'),
                'wp.newCategory'            => array($this, 'wpNewCategory'),
                'wp.suggestCategories'      => array($this, 'wpSuggestCategories'),
                'wp.uploadFile'             => array($this, 'mwNewMediaObject'),
                
                /** New Wordpress API since 2.9.2 */
                'wp.getUsersBlogs'          => array($this, 'wpGetUsersBlogs'),
                'wp.getTags'                => array($this, 'wpGetTags'),
                'wp.deleteCategory'         => array($this, 'wpDeleteCategory'),
                'wp.getCommentCount'        => array($this, 'wpGetCommentCount'),
                'wp.getPostStatusList'      => array($this, 'wpGetPostStatusList'),
                'wp.getPageStatusList'      => array($this, 'wpGetPageStatusList'),
                'wp.getPageTemplates'       => array($this, 'wpGetPageTemplates'),
                'wp.getOptions'             => array($this, 'wpGetOptions'),
                'wp.setOptions'             => array($this, 'wpSetOptions'),
                'wp.getComment'             => array($this, 'wpGetComment'),
                'wp.getComments'            => array($this, 'wpGetComments'),
                'wp.deleteComment'          => array($this, 'wpDeleteComment'),
                'wp.editComment'            => array($this, 'wpEditComment'),
                'wp.newComment'             => array($this, 'wpNewComment'),
                'wp.getCommentStatusList'   => array($this, 'wpGetCommentStatusList'),

                /** New Wordpress API after 2.9.2 */
                'wp.getProfile'             => array($this, 'wpGetProfile'),
                'wp.getPostFormats'         => array($this, 'wpGetPostFormats'),
                'wp.getMediaLibrary'        => array($this, 'wpGetMediaLibrary'),
                'wp.getMediaItem'           => array($this, 'wpGetMediaItem'),
                'wp.editPost'               => array($this, 'wpEditPost'),

                /** Blogger API */
                'blogger.getUsersBlogs'     => array($this, 'bloggerGetUsersBlogs'),
                'blogger.getUserInfo'       => array($this, 'bloggerGetUserInfo'),
                'blogger.getPost'           => array($this, 'bloggerGetPost'),
                'blogger.getRecentPosts'    => array($this, 'bloggerGetRecentPosts'),
                'blogger.getTemplate'       => array($this, 'bloggerGetTemplate'),
                'blogger.setTemplate'       => array($this, 'bloggerSetTemplate'),
                'blogger.deletePost'        => array($this, 'bloggerDeletePost'),

                /** MetaWeblog API (with MT extensions to structs) */
                'metaWeblog.newPost'        => array($this, 'mwNewPost'),
                'metaWeblog.editPost'       => array($this, 'mwEditPost'),
                'metaWeblog.getPost'        => array($this, 'mwGetPost'),
                'metaWeblog.getRecentPosts' => array($this, 'mwGetRecentPosts'),
                'metaWeblog.getCategories'  => array($this, 'mwGetCategories'),
                'metaWeblog.newMediaObject' => array($this, 'mwNewMediaObject'),

                /** MetaWeblog API aliases for Blogger API */
                'metaWeblog.deletePost'     => array($this, 'bloggerDeletePost'),
                'metaWeblog.getTemplate'    => array($this, 'bloggerGetTemplate'),
                'metaWeblog.setTemplate'    => array($this, 'bloggerSetTemplate'),
                'metaWeblog.getUsersBlogs'  => array($this, 'bloggerGetUsersBlogs'),

                /** MovableType API */
                'mt.getCategoryList'        => array($this, 'mtGetCategoryList'),
                'mt.getRecentPostTitles'    => array($this, 'mtGetRecentPostTitles'),
                'mt.getPostCategories'      => array($this, 'mtGetPostCategories'),
                'mt.setPostCategories'      => array($this, 'mtSetPostCategories'),
                'mt.publishPost'            => array($this, 'mtPublishPost'),

                /** PingBack */
                'pingback.ping'             => array($this,'pingbackPing'),
                'pingback.extensions.getPingbacks' => array($this,'pingbackExtensionsGetPingbacks'),
                
                /** hook after */
                'hook.afterCall'            => array($this, 'hookAfterCall'),
            ));
        }
    }
}
