<?php

if (!defined('ZBP_PATH')) {
    exit('Access denied');
}

/**
 * 文章分类类.
 *
 * @property int|string ID
 * @property string Name 分类名
 * @property string Alias 别名
 * @property int|string Count 分类下文章数量
 * @property int|string RootID 祖先分类ID
 * @property int|string ParentID 父分类ID
 * @property string Symbol 用于后台分类管理的“层次标识符”，无用处，待改名
 * @property int|string Level 分类层级
 * @property string Template 分类模板
 * @property string LogTemplate 分类下文章模板
 * @property string Url
 * @property int|string Order 分类顺序
 * @property string SymbolName 层次标识符+名字
 * @property int AllCount 本分类及子孙分类下所有文章数量
 */
class Category extends Base
{

    /**
     * @var array 下层分类
     */
    public $SubCategories = array(); //子分类

    /**
     * @deprecated
     *
     * @var array|null
     */
    public $SubCategorys = null; // 拼写错误，保持兼容

    public $ChildrenCategories = array(); //子孙分类

    /**
     * 构造函数.
     */
    public function __construct()
    {
        global $zbp;
        parent::__construct($zbp->table['Category'], $zbp->datainfo['Category'], __CLASS__);

        $this->SubCategorys = &$this->SubCategories;
        $this->Name = $zbp->lang['msg']['unnamed'];
    }

    /**
     * 魔术方法：重载，可通过接口Filter_Plugin_Category_Call添加自定义函数.
     *
     * @api Filter_Plugin_Category_Call
     *
     * @param string $method 方法
     * @param mixed  $args   参数
     *
     * @return mixed
     */
    public function __call($method, $args)
    {
        foreach ($GLOBALS['hooks']['Filter_Plugin_Category_Call'] as $fpname => &$fpsignal) {
            $fpreturn = $fpname($this, $method, $args);
            if ($fpsignal == PLUGIN_EXITSIGNAL_RETURN) {
                $fpsignal = PLUGIN_EXITSIGNAL_NONE;

                return $fpreturn;
            }
        }
    }

    /**
     * @param $name
     * @param $value
     */
    public function __set($name, $value)
    {
        global $zbp;
        if (in_array($name, array('Url', 'Symbol', 'Level', 'SymbolName', 'Parent'))) {
            return;
        } elseif ($name == 'Template') {
            if ($value == $zbp->option['ZC_INDEX_DEFAULT_TEMPLATE']) {
                $value = '';
            }
            $this->data[$name] = $value;

            return;
        }
        if ($name == 'LogTemplate') {
            if ($value == $zbp->option['ZC_POST_DEFAULT_TEMPLATE']) {
                $value = '';
            }
            $this->data[$name] = $value;

            return;
        }
        foreach ($GLOBALS['hooks']['Filter_Plugin_Category_Set'] as $fpname => &$fpsignal) {
            $fpreturn = $fpname($this, $name, $value);
        }
        parent::__set($name, $value);
    }

    /**
     * @param $name
     *
     * @return int|mixed|null|string
     */
    public function __get($name)
    {
        global $zbp;
        if ($name == 'Url') {
            foreach ($GLOBALS['hooks']['Filter_Plugin_Category_Url'] as $fpname => &$fpsignal) {
                $fpreturn = $fpname($this);
                if ($fpsignal == PLUGIN_EXITSIGNAL_RETURN) {
                    $fpsignal = PLUGIN_EXITSIGNAL_NONE;

                    return $fpreturn;
                }
            }
            $backAttr = $zbp->option['ZC_ALIAS_BACK_ATTR'];
            $u = new UrlRule($zbp->option['ZC_CATEGORY_REGEX']);
            $u->Rules['{%id%}'] = $this->ID;
            $u->Rules['{%alias%}'] = $this->Alias == '' ? $this->$backAttr : $this->Alias;

            return $u->Make();
        }
        if ($name == 'Symbol') {
            if ($this->ParentID == 0) {
                return;
            } else {
                $l = $this->Level;

                return str_repeat('&nbsp;', ($l * 2 - 1)) . '└';
            }
        }
        if ($name == 'Level') {
            return $this->GetDeep($this);
        }
        if ($name == 'SymbolName') {
            return $this->Symbol . htmlspecialchars($this->Name);
        }
        if ($name == 'Parent') {
            if ($this->ParentID == 0) {
                return;
            } else {
                return $zbp->categories[$this->ParentID];
            }
        }
        if ($name == 'Template') {
            $value = $this->data[$name];
            if ($value == '') {
                $value = $zbp->option['ZC_INDEX_DEFAULT_TEMPLATE'];
            }

            return $value;
        }
        if ($name == 'LogTemplate') {
            $value = $this->data[$name];
            if ($value == '') {
                $value = $zbp->option['ZC_POST_DEFAULT_TEMPLATE'];
            }

            return $value;
        }
        if ($name == 'AllCount') {
            $i = $this->Count;
            foreach ($this->ChildrenCategories as $c) {
                $i += $c->Count;
            }
            return $i;
        }
        foreach ($GLOBALS['hooks']['Filter_Plugin_Category_Get'] as $fpname => &$fpsignal) {
            $fpreturn = $fpname($this, $name);
            if ($fpsignal == PLUGIN_EXITSIGNAL_RETURN) {
                $fpsignal = PLUGIN_EXITSIGNAL_NONE;

                return $fpreturn;
            }
        }

        return parent::__get($name);
    }

    /**
     * 保存分类数据.
     *
     * @return bool
     */
    public function Save()
    {
        global $zbp;
        if ($this->Template == $zbp->option['ZC_INDEX_DEFAULT_TEMPLATE']) {
            $this->data['Template'] = '';
        }

        if ($this->LogTemplate == $zbp->option['ZC_POST_DEFAULT_TEMPLATE']) {
            $this->data['LogTemplate'] = '';
        }

        $this->RootID = (int) $this->GetRoot($this->ParentID);

        foreach ($GLOBALS['hooks']['Filter_Plugin_Category_Save'] as $fpname => &$fpsignal) {
            $fpreturn = $fpname($this);
            if ($fpsignal == PLUGIN_EXITSIGNAL_RETURN) {
                $fpsignal = PLUGIN_EXITSIGNAL_NONE;

                return $fpreturn;
            }
        }

        return parent::Save();
    }

    /**
     * @return bool
     */
    public function Del()
    {
        global $zbp;
        if ($this->ID > 0) {
            unset($zbp->categories[$this->ID]);
            unset($zbp->categoriesbyorder[$this->ID]);
        }

        foreach ($GLOBALS['hooks']['Filter_Plugin_Category_Del'] as $fpname => &$fpsignal) {
            $fpreturn = $fpname($this);
            if ($fpsignal == PLUGIN_EXITSIGNAL_RETURN) {
                $fpsignal = PLUGIN_EXITSIGNAL_NONE;

                return $fpreturn;
            }
        }

        return parent::Del();
    }

    /**
     * 得到分类深度.
     *
     * @param object $object
     * @param int    $deep
     *
     * @return int 分类深度
     */
    private function GetDeep(&$object, $deep = 0)
    {
        global $zbp;
        if ($object->ParentID == 0) {
            return $deep;
        } elseif (!isset($zbp->categories[$object->ParentID])) {
            return 0;
        } else {
            return $this->GetDeep($zbp->categories[$object->ParentID], ($deep + 1));
        }
    }

    /**
     * 得到分类RootID.
     *
     * @param int 父分类ID
     *
     * @return int 祖分类ID
     */
    private function GetRoot($parentid)
    {
        global $zbp;
        if ($parentid == 0) {
            return 0;
        }
        if (isset($zbp->categories[$parentid])) {
            if ($zbp->categories[$parentid]->ParentID > 0) {
                return $this->GetRoot($zbp->categories[$parentid]->ParentID);
            }

            return $parentid;
        } else {
            return 0;
        }
    }

}
