<?php
/**
 * Comment model.
 *
 * @package koubel homepage
 * @author Miroslav Kubelik (koubel@volny.cz)
 * @copyright Copyright (c) 2007-2009 Miroslav Kubelik
 * @license http://opensource.org/licenses/gpl-license.php GNU GPL
 */

/**
 * Comment model class
 *
 * @package koubel homepage
 * @author Miroslav Kubelik (koubel@volny.cz)
 * @copyright Copyright (c) 2007-2009 Miroslav Kubelik
 * @license http://opensource.org/licenses/gpl-license.php GNU GPL
 */
class Blog_Model_Comment extends Blog_Model_Model
{
    /**
     * id of comment
     * @var int
     */
    private $_id;
    
    /**
     * id of article to which the comment belogs
     * @var int
     */
    private $_articleId;

    private $_message;

    private $_authorName;

    private $_authorWWW;

    private $_authorEmail;

    private $_posted;


    protected function _setDefaultDao()
    {
        $this->setDao(new Blog_Model_Dao_Comment());
    }

    public function getAll($pageNo=null,$perPageItems=null)
    {
        $rows=$this->getDao()->fetchAllItems($pageNo,$perPageItems);
        return $this->_getSet($rows);
    }

    /**
     * Return paginator from {@link Model::$dao}
     * @return Zend_Paginator
     */
    public function getPaginator() {
        return $this->getDao()->getPaginator();
    }

    public function getId()
    {
        return $this->_id;
    }

    public function setId($id)
    {
        $this->_id=$id;
    }

    public function getArticleId()
    {
        return $this->_articleId;
    }

    public function setArticleId($id)
    {
        $this->_articleId=$id;
    }

    /**
     * Gets article for it current comment is.
     * @return Blog_Model_Article
     */
    public function getArticle()
    {
        $article=new Blog_Model_Article();
        $article->setByComment($this);

        return $article;
    }

    /**
     * Returns the comment order for an article. Comments are sorted in ascending
     * order.
     *
     * Just proxy for the same dao method.
     * @return int
     */
    public function getOrderforArticle()
    {
        return $this->getDao()->getOrderforArticle($this->_id,$this->_articleId);
    }

    public function getMessage()
    {
        return $this->_message;
    }

    public function setMessage($message)
    {
        $this->_message=$message;
    }

    public function getAuthorName()
    {
        return $this->_authorName;
    }

    public function setAuthorName($name)
    {
        $this->_authorName=$name;
    }

    public function getAuthorWWW()
    {
        return $this->_authorWWW;
    }

    public function setAuthorWWW($www)
    {
        $this->_authorWWW=$www;
    }

    public function getAuthorEmail()
    {
        return $this->_authorEmail;
    }

    public function setAuthorEmail($email)
    {
        $this->_authorEmail=$email;
    }

    public function getPosted()
    {
        return $this->_posted;
    }

    public function setPosted($dateTime)
    {
        $this->_posted=$dateTime;
    }

    public function getByArticle(Blog_Model_Article $article)
    {
        $currentArticle=$article->getDaoRow();
        $articleComments = $currentArticle->findDependentRowset("Blog_Model_Dao_Comment");

        return $this->_getSet($articleComments);
    }

    public function getCountByArticle(Blog_Model_Article $article)
    {
        return $this->getDao()->getCountByArticle($article->getId());
    }

    public function findById($id)
    {
        $row=$this->getDao()->find($id)->current();
        $this->_setFromDaoRow($row->toArray());
    }

    public function insert()
    {
        $this->getDao()->insert(array(
            "article_id"=>$this->_articleId,
            "message"=>$this->_message,
            "name"=>$this->_authorName,
            "email"=>$this->_authorEmail,
            "www"=> (empty($this->_authorWWW)? NULL : $this->_authorWWW),
            "posted"=>new Zend_Db_Expr('NOW()')
        ));
    }

    public function update()
    {
        $this->getDao()->update(
            array(
                "message"=>$this->_message,
                "name"=>$this->_authorName,
                "email"=>$this->_authorEmail,
                "www"=> (empty($this->_authorWWW)? NULL : $this->_authorWWW),
                "posted"=>$this->_posted
            ), "id=$this->_id"
        );
    }

    public function delete()
    {
        $this->getDao()->delete("id=$this->_id");
    }

    /**
     * Gets database row object which corresponds our current properties.
     * It is used mostly for the operation with the relationship. Hence we need
     * to set only keys
     * @param bool $keyOnly true - sets only key properties (primary and foreign) it is
     * enough in most situations, false - sets all properties
     * @return Zend_Db_Table_Row_Abstract
     */
    public function getDaoRow($keyOnly=true)
    {
        $data = array(
            "id"=>$this->_id,
            "article_id"=>$this->_articleId
        );

        if (!$keyOnly) {
            $data["message"]=$this->_message;
            $data["name"]=$this->_authorName;
            $data["www"]=$this->_authorWWW;
            $data["email"]=$this->_authorEmail;
            $data["posted"]=$this->_posted;
        }

        $row=$this->getDao()->createRow($data);
        return $row;
    }

    protected function _setPropFromArray(&$arr)
    {
        foreach($arr as $key=>$val) {
            $this->{"_".$key}=$val;
        }
    }

    protected function _inflectDaoRowIndexes(&$arr)
    {
        $notAllowedIndexes=array("dao");

        $keys=array_keys($arr);
        foreach($keys as $key) {
            //unset not allowed indexes
            if (in_array($key,$notAllowedIndexes))
                throw new Exception("you cannot use $key index as the column index");

            switch ($key) {
            case "article_id":
                MKLib_Utils::renameKey($arr,$key,"articleId");
                break;
            case "name":
                MKLib_Utils::renameKey($arr,$key,"authorName");
                break;
            case "www":
                MKLib_Utils::renameKey($arr,$key,"authorWWW");
                break;
            case "email":
                MKLib_Utils::renameKey($arr,$key,"authorEmail");
                break;
            default:
                break;
            }
        }
    }

    /**
     * Makes html special chars conversion for all text in the <pre> tag for a whole
     * comment text.
     * @param string $message comment text as the html
     * @return string
     */
    public static function escapePre($message)
    {
        $pattern = "/<pre>((\\n|.)*)<\/pre>/U";
        $text=preg_replace_callback($pattern,array('Blog_Model_Comment', 'escapePreCallback'),$message);
        return $text;
    }

    /**
     * Callback for the {@link Comment::escapePre()}
     * @param array $matches array with matches strings
     * @return string
     */
    public static function escapePreCallback($matches)
    {
        return "<pre>".htmlspecialchars($matches[1])."</pre>";
    }

    /**
     * Prepares comment text before the addition into the database
     * @param string $text
     * @return string
     */
    public static function prepareCommentText($text)
    {
        //special chars for <pre> tag content first
        $text=self::escapePre($text);
        $text=preg_replace("/\s+(<pre)/","\\1",$text);
        $text=preg_replace("/(pre>)\s*/","\\1",$text);

        $filter=new Zend_Filter_StripTags(array("a","pre"),array("href"));
        $text=$filter->filter($text);

        return $text;
    }

    /**
     * Gets comment text in format, in which will be in the web page.
     *
     * Maybe better usage of this method is as view helper, but we need this functionality
     * in other places (e.g. rss feeds) when usage of the view helper is more problematic.
     *
     * @param string $text
     * @return string
     */
    public static function commentBody($text)
    {
        //replace line breaks with <br \>
        $text=nl2br($text);

        //remove <br /> from the <pre> tags
        $pattern = "/<pre>((\\n|.)*)<\/pre>/U";
        $text=preg_replace_callback($pattern,
            array('Blog_Model_Comment', 'removeBrCallback'),$text
        );

        return $text;
    }

    /**
     * Callback for the commentBody method, which removes <br />
     * @param array $matches array with matches strings
     * @return string
     */
    public static function removeBrCallback($matches)
    {
        return "<pre>".str_replace("<br />","",$matches[1])."</pre>";
    }
}
