parameter->setDefault('ignore=0¤t='); $select = $this->select()->where('type = ?', 'category'); if ($this->parameter->ignore) { $select->where('mid <> ?', $this->parameter->ignore); } $categories = $this->db->fetchAll($select->order('table.metas.order', Typecho_Db::SORT_ASC)); foreach ($categories as $category) { $category['levels'] = 0; $this->_map[$category['mid']] = $category; } // 读取数据 foreach ($this->_map as $mid => $category) { $parent = $category['parent']; if (0 != $parent && isset($this->_map[$parent])) { $this->_treeViewCategories[$parent][] = $mid; } else { $this->_top[] = $mid; } } // 预处理深度 $this->levelWalkCallback($this->_top); $this->_map = array_map(array($this, 'filter'), $this->_map); } /** * 列出分类回调 * * @access private */ private function treeViewCategoriesCallback() { $categoryOptions = $this->_categoryOptions; if (function_exists('treeViewCategories')) { return treeViewCategories($this, $categoryOptions); } $classes = array(); if ($categoryOptions->itemClass) { $classes[] = $categoryOptions->itemClass; } $classes[] = 'category-level-' . $this->levels; echo '<' . $categoryOptions->itemTag . ' class="' . implode(' ', $classes); if ($this->levels > 0) { echo ' category-child'; $this->levelsAlt(' category-level-odd', ' category-level-even'); } else { echo ' category-parent'; } if ($this->mid == $this->parameter->current) { echo ' category-active'; } else if (isset($this->_children[$this->mid]) && in_array($this->parameter->current, $this->_children[$this->mid])) { echo ' category-parent-active'; } echo '">' . $this->name . ''; if ($categoryOptions->showCount) { printf($categoryOptions->countTemplate, intval($this->count)); } if ($categoryOptions->showFeed) { printf($categoryOptions->feedTemplate, $this->feedUrl); } if ($this->children) { $this->treeViewCategories(); } echo 'itemTag . '>'; } /** * 预处理分类迭代 * * @param array $categories * @param array $parents * @access private */ private function levelWalkCallback(array $categories, $parents = array()) { foreach ($parents as $parent) { if (!isset($this->_children[$parent])) { $this->_children[$parent] = array(); } $this->_children[$parent] = array_merge($this->_children[$parent], $categories); } foreach ($categories as $mid) { $this->_orders[] = $mid; $parent = $this->_map[$mid]['parent']; if (0 != $parent && isset($this->_map[$parent])) { $levels = $this->_map[$parent]['levels'] + 1; $this->_map[$mid]['levels'] = $levels; } $this->_parents[$mid] = $parents; if (!empty($this->_treeViewCategories[$mid])) { $new = $parents; $new[] = $mid; $this->levelWalkCallback($this->_treeViewCategories[$mid], $new); } } } /** * 子评论 * * @access protected * @return array */ protected function ___children() { return isset($this->_treeViewCategories[$this->mid]) ? $this->getCategories($this->_treeViewCategories[$this->mid]) : array(); } /** * 执行函数 * * @access public * @return void */ public function execute() { $this->stack = $this->getCategories($this->_orders); } /** * treeViewCategories * * @access public * @return void */ public function treeViewCategories() { $children = $this->children; if ($children) { //缓存变量便于还原 $tmp = $this->row; $this->sequence ++; //在子评论之前输出 echo '<' . $this->_categoryOptions->wrapTag . (empty($this->_categoryOptions->wrapClass) ? '' : ' class="' . $this->_categoryOptions->wrapClass . '"') . '>'; foreach ($children as $child) { $this->row = $child; $this->treeViewCategoriesCallback(); $this->row = $tmp; } //在子评论之后输出 echo '_categoryOptions->wrapTag . '>'; $this->sequence --; } } /** * treeViewCategories * * @param $categoryOptions 输出选项 * @access public * @return void */ public function listCategories($categoryOptions = NULL) { //初始化一些变量 $this->_categoryOptions = Typecho_Config::factory($categoryOptions); $this->_categoryOptions->setDefault(array( 'wrapTag' => 'ul', 'wrapClass' => '', 'itemTag' => 'li', 'itemClass' => '', 'showCount' => false, 'showFeed' => false, 'countTemplate' => '(%d)', 'feedTemplate' => 'RSS' )); // 插件插件接口 $this->pluginHandle()->trigger($plugged)->listCategories($this->_categoryOptions, $this); if (!$plugged) { $this->stack = $this->getCategories($this->_top); if ($this->have()) { echo '<' . $this->_categoryOptions->wrapTag . (empty($this->_categoryOptions->wrapClass) ? '' : ' class="' . $this->_categoryOptions->wrapClass . '"') . '>'; while ($this->next()) { $this->treeViewCategoriesCallback(); } echo '_categoryOptions->wrapTag . '>'; } $this->stack = $this->_map; } } /** * 根据深度余数输出 * * @access public * @return void */ public function levelsAlt() { $args = func_get_args(); $num = func_num_args(); $split = $this->levels % $num; echo $args[(0 == $split ? $num : $split) -1]; } /** * 将每行的值压入堆栈 * * @access public * @param array $value 每行的值 * @return array */ public function filter(array $value) { $value['directory'] = $this->getAllParentsSlug($value['mid']); $value['directory'][] = $value['slug']; $tmpCategoryTree = $value['directory']; $value['directory'] = implode('/', array_map('urlencode', $value['directory'])); $value = parent::filter($value); $value['directory'] = $tmpCategoryTree; return $value; } /** * 获取某个分类下的所有子节点 * * @param mixed $mid * @access public * @return array */ public function getAllChildren($mid) { return isset($this->_children[$mid]) ? $this->_children[$mid] : array(); } /** * 获取某个分类所有父级节点 * * @param mixed $mid * @access public * @return array */ public function getAllParents($mid) { $parents = array(); if (isset($this->_parents[$mid])) { foreach ($this->_parents[$mid] as $parent) { $parents[] = $this->_map[$parent]; } } return $parents; } /** * 获取某个分类所有父级节点缩略名 * * @param mixed $mid * @access public * @return array */ public function getAllParentsSlug($mid) { $parents = array(); if (isset($this->_parents[$mid])) { foreach ($this->_parents[$mid] as $parent) { $parents[] = $this->_map[$parent]['slug']; } } return $parents; } /** * 获取单个分类 * * @param integer $mid * @access public * @return mixed */ public function getCategory($mid) { return isset($this->_map[$mid]) ? $this->_map[$mid] : NULL; } /** * 获取多个分类 * * @param mixed $mids * @access public * @return array */ public function getCategories($mids) { $result = array(); if (!empty($mids)) { foreach ($mids as $mid) { $result[] = $this->_map[$mid]; } } return $result; } }