<?php
/**

  • Typecho 主题 functions.php 文件
  • 包含主题配置和智能分类显示数量继承功能
    */

if (!defined('__TYPECHO_ROOT_DIR__')) exit;

// ==================== 主题配置部分 ====================
function themeConfig($form)
{

// 站点 LOGO 设置
$logoUrl = new \Typecho\Widget\Helper\Form\Element\Text(
    'logoUrl',
    null,
    null,
    _t('站点 LOGO 地址'),
    _t('在这里填入一个图片 URL 地址, 以在网站标题前加上一个 LOGO')
);
$form->addInput($logoUrl);

// 侧边栏显示设置
$sidebarBlock = new \Typecho\Widget\Helper\Form\Element\Checkbox(
    'sidebarBlock',
    [
        'ShowRecentPosts'    => _t('显示最新文章'),
        'ShowRecentComments' => _t('显示最近回复'),
        'ShowCategory'       => _t('显示分类'),
        'ShowArchive'        => _t('显示归档'),
        'ShowOther'          => _t('显示其它杂项')
    ],
    ['ShowRecentPosts', 'ShowRecentComments', 'ShowCategory', 'ShowArchive', 'ShowOther'],
    _t('侧边栏显示')
);
$form->addInput($sidebarBlock->multiMode());

// 添加分类显示数量设置说明
$categoryDesc = new \Typecho\Widget\Helper\Form\Element\Textarea(
    'categoryDesc',
    null,
    _t("分类显示数量设置说明:\n\n1. news分类及其子分类:10篇/页\n2. technology分类及其子分类:12篇/页\n3. life分类及其子分类:8篇/页\n4. 其他分类使用后台全局设置"),
    _t('分类显示数量说明'),
    _t('智能继承:子分类自动继承父分类的显示设置,除非单独指定。')
);
$form->addInput($categoryDesc);

}

// ==================== 智能分类管理器 ====================

/**

  • 分类智能继承管理器
  • 功能:自动识别分类层级关系,子分类继承父分类的显示设置
    */

class SmartCategoryManager
{

/**
 * 分类显示数量配置
 * 格式:['分类标识' => 显示篇数]
 * 分类标识可以是:别名 或 ID
 * 
 * 优先级:子分类单独设置 > 继承父分类设置 > 全局设置
 */
private static $categoryConfig = [
    // ===== 父分类配置 =====
    // 使用分类别名
    'news'       => 10,  // 新闻主分类:10篇
    'technology' => 12,  // 技术主分类:12篇
    'life'       => 8,   // 生活主分类:8篇
    'reviews'    => 6,   // 评测主分类:6篇
    
    // 使用分类ID(如果不知道别名,可以用ID)
    // '1' => 10,      // 分类ID为1:10篇
    // '2' => 12,      // 分类ID为2:12篇
    
    // ===== 子分类单独配置(如果需要特殊设置) =====
    'news-mobile'   => 15,  // news的子分类,但单独显示15篇(不继承)
    'tech-android'  => 20,  // technology的子分类,单独显示20篇
    // 其他子分类会自动继承父分类设置
];

/**
 * 分类别名到ID的映射缓存
 */
private static $slugToIdCache = [];

/**
 * 分类ID到信息的映射缓存
 */
private static $categoryCache = [];

/**
 * 获取分类完整信息
 */
private static function getCategoryInfo($identifier)
{
    // 先从缓存读取
    $cacheKey = $identifier;
    if (isset(self::$categoryCache[$cacheKey])) {
        return self::$categoryCache[$cacheKey];
    }
    
    $db = Typecho_Db::get();
    $info = null;
    
    try {
        // 尝试作为ID或别名查询
        $info = $db->fetchRow($db->select('mid', 'name', 'slug', 'parent')
            ->from('table.metas')
            ->where('mid = ?', $identifier)
            ->orWhere('slug = ?', $identifier)
            ->limit(1));
            
        if ($info) {
            // 缓存映射关系
            self::$slugToIdCache[$info['slug']] = $info['mid'];
            self::$categoryCache[$info['mid']] = $info;
            self::$categoryCache[$info['slug']] = $info;
        }
    } catch (Exception $e) {
        // 出错时返回null
    }
    
    return $info;
}

/**
 * 获取父分类链(从当前分类到顶级分类)
 */
private static function getParentChain($categoryId)
{
    $chain = [];
    $currentId = $categoryId;
    
    while ($currentId > 0) {
        $info = self::getCategoryInfo($currentId);
        if (!$info) break;
        
        $chain[] = $info;
        $currentId = $info['parent'];
        
        // 防止无限循环
        if (count($chain) > 10) break;
    }
    
    return $chain;
}

/**
 * 智能获取分类应该显示的数量
 * @param string $identifier 分类标识(ID或别名)
 * @return int|null 显示数量,null表示使用全局设置
 */
public static function getSmartPageSize($identifier)
{
    // 1. 检查是否有直接配置
    if (isset(self::$categoryConfig[$identifier])) {
        return self::$categoryConfig[$identifier];
    }
    
    // 2. 获取分类信息
    $categoryInfo = self::getCategoryInfo($identifier);
    if (!$categoryInfo) {
        return null; // 分类不存在,使用全局设置
    }
    
    $categoryId = $categoryInfo['mid'];
    $categorySlug = $categoryInfo['slug'];
    
    // 3. 再次检查(可能在缓存中)
    if (isset(self::$categoryConfig[$categoryId])) {
        return self::$categoryConfig[$categoryId];
    }
    if (isset(self::$categoryConfig[$categorySlug])) {
        return self::$categoryConfig[$categorySlug];
    }
    
    // 4. 如果是子分类,尝试继承父分类设置
    if ($categoryInfo['parent'] > 0) {
        $parentChain = self::getParentChain($categoryId);
        
        foreach ($parentChain as $parent) {
            // 检查父分类的ID
            if (isset(self::$categoryConfig[$parent['mid']])) {
                return self::$categoryConfig[$parent['mid']];
            }
            
            // 检查父分类的别名
            if (isset(self::$categoryConfig[$parent['slug']])) {
                return self::$categoryConfig[$parent['slug']];
            }
        }
    }
    
    // 5. 检查是否是某个配置分类的子分类(通过命名约定)
    foreach (self::$categoryConfig as $configSlug => $pageSize) {
        // 如果配置的分类名是当前分类名的前缀
        if (strpos($categorySlug, $configSlug . '-') === 0) {
            return $pageSize;
        }
    }
    
    // 6. 没有找到配置,使用全局设置
    return null;
}

/**
 * 获取所有配置信息(用于调试)
 */
public static function getConfigInfo()
{
    return [
        'config' => self::$categoryConfig,
        'cache_size' => count(self::$categoryCache),
        'slug_map' => self::$slugToIdCache
    ];
}

/**
 * 添加或更新分类配置(可选功能)
 */
public static function updateConfig($identifier, $pageSize)
{
    self::$categoryConfig[$identifier] = $pageSize;
}

}

// ==================== 主题初始化 ====================

/**

  • 主题初始化函数
    */

function themeInit($archive)
{

// 只在分类页面生效
if ($archive->is('category')) {
    // 获取当前分类标识(从URL参数)
    $categorySlug = $archive->getArchiveSlug();
    
    if (empty($categorySlug)) {
        // 尝试从请求中获取
        $categorySlug = $archive->request->get('category');
    }
    
    if (!empty($categorySlug)) {
        // 获取智能计算后的显示数量
        $pageSize = SmartCategoryManager::getSmartPageSize($categorySlug);
        
        if ($pageSize !== null) {
            $archive->parameter->pageSize = $pageSize;
            
            // ===== 调试信息(正式使用时注释掉) =====
            /*
            $debugInfo = SmartCategoryManager::getConfigInfo();
            error_log("智能分类设置生效:");
            error_log("  当前分类标识: {$categorySlug}");
            error_log("  设置显示数量: {$pageSize}");
            error_log("  总配置数: " . count($debugInfo['config']));
            */
        }
    }
}

}

// ==================== 调试和辅助功能 ====================

/**

  • 调试函数:显示分类层级信息
    */

function debugCategoryHierarchy()
{

if (isset($_GET['debug_category']) && $_GET['debug_category'] == '1') {
    $archive = Typecho_Widget::widget('Widget_Archive');
    
    if ($archive->is('category')) {
        $categorySlug = $archive->getArchiveSlug();
        
        echo "<!-- ===== 分类调试信息 ===== -->\n";
        echo "<!-- 当前分类标识: {$categorySlug} -->\n";
        
        $pageSize = SmartCategoryManager::getSmartPageSize($categorySlug);
        echo "<!-- 智能计算显示数量: " . ($pageSize !== null ? $pageSize : '使用全局设置') . " -->\n";
        
        $configInfo = SmartCategoryManager::getConfigInfo();
        echo "<!-- 配置总数: " . count($configInfo['config']) . " -->\n";
        echo "<!-- 缓存大小: " . $configInfo['cache_size'] . " -->\n";
        
        // 显示配置详情
        foreach ($configInfo['config'] as $key => $value) {
            echo "<!-- 配置项: {$key} => {$value}篇 -->\n";
        }
        
        echo "<!-- ===== 调试信息结束 ===== -->\n";
    }
}

}

// 注册调试函数(正式使用时注释掉)
// add_action('init', 'debugCategoryHierarchy');

/**

  • 简化的分类显示函数(用于模板中调用)
    */

function getCategoryDisplayInfo($categorySlug = null)
{

if ($categorySlug === null) {
    $archive = Typecho_Widget::widget('Widget_Archive');
    $categorySlug = $archive->getArchiveSlug();
}

$pageSize = SmartCategoryManager::getSmartPageSize($categorySlug);
return [
    'slug' => $categorySlug,
    'page_size' => $pageSize,
    'is_custom' => $pageSize !== null
];

}

/**

  • 模板函数:在侧边栏显示分类数量设置
    */

function showCategoryPageSizeSettings()
{

echo '<div class="widget category-settings">';
echo '<h3 class="widget-title">分类显示设置</h3>';
echo '<ul>';

$config = [
    'news' => 10,
    'technology' => 12,
    'life' => 8,
    'reviews' => 6,
];

foreach ($config as $name => $size) {
    echo "<li>{$name}分类: {$size}篇/页</li>";
}

echo '<li>其他分类: 使用全局设置</li>';
echo '<li>子分类自动继承父分类设置</li>';
echo '</ul>';
echo '</div>';

}

// ==================== 示例配置说明 ====================
/*

  • 如何使用本系统:
    1. 基本配置:
  • 在 SmartCategoryManager::$categoryConfig 中配置父分类
  • 例如:'news' => 10 表示news分类显示10篇
    1. 子分类继承:
  • 所有news的子分类会自动继承10篇的设置
  • 除非在配置中单独指定
    1. 单独配置子分类:
  • 如果某个子分类需要不同的设置,直接配置:
  • 'news-mobile' => 15 // news-mobile显示15篇
    1. 支持分类ID:
  • 如果不知道分类别名,可以用ID:
  • '1' => 10 // 分类ID为1显示10篇
    1. 命名约定继承:
  • 如果子分类别名以父分类别名开头,也会继承
  • 例如:news-iphone, news-android 都会继承news的设置
  • 示例分类结构:
  • news (10篇)
  • ├── news-mobile (15篇,单独配置)
  • ├── news-pc (10篇,自动继承)
  • └── news-tablet (10篇,自动继承)
  • technology (12篇)
  • └── tech-phone (12篇,自动继承)
    */

// ==================== 初始化检查 ====================
/**

  • 检查必要函数是否存在
    */

function checkThemeRequirements()
{

if (!function_exists('Typecho_Db::get')) {
    error_log('Typecho数据库函数不可用,请检查Typecho安装');
}

}

// 执行检查
add_action('init', 'checkThemeRequirements');

标签: none

添加新评论