Dokuwiki 命名空间排序分页

根据您之前的讨论和DokuWiki的代码结构,我将为您实现一个按日期排序并分页显示命名空间下页面的功能。这个功能可以通过两种方式实现:自定义action方法或自定义语法插件。

最佳实现方式:自定义Action方法

对于这种功能,自定义Action方法是更合适的选择,原因如下:

  1. 这是一个页面级别的功能,需要处理整个页面的显示
  2. 需要处理URL参数(如页码、命名空间等)
  3. 与DokuWiki的现有分页机制更容易集成

实现步骤

1. 创建插件目录结构

首先,创建一个名为datepages的动作插件:

lib/plugins/datepages/  
├── action.php  
├── syntax.php (可选,如果需要语法标记)  
└── style.css (可选,用于样式)

2. 实现Action插件

以下是action.php的实现代码:

<?php  
/**  
 * DokuWiki Plugin datepages (Action Component)  
 *  
 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html  
 * @author  Your Name  
 */  

class action_plugin_datepages extends DokuWiki_Action_Plugin {  

    /**  
     * 注册事件处理器  
     */  
    public function register(Doku_Event_Handler $controller) {  
        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handleDatepages');  
        $controller->register_hook('TPL_ACT_UNKNOWN', 'BEFORE', $this, 'handleDisplay');  
    }  

    /**  
     * 处理datepages动作  
     */  
    public function handleDatepages(Doku_Event $event, $param) {  
        if($event->data != 'datepages') return;  

        // 标记为已处理  
        $event->preventDefault();  
    }  

    /**  
     * 显示按日期排序的页面列表  
     */  
    public function handleDisplay(Doku_Event $event, $param) {  
        global $ACT, $INPUT, $INFO, $conf;  

        if($ACT != 'datepages') return;  

        // 阻止默认处理  
        $event->preventDefault();  

        // 获取参数  
        $ns = $INPUT->str('ns', getNS($INFO['id']));  
        $offset = $INPUT->int('offset', 0);  
        $limit = $INPUT->int('limit', 10); // 默认每页10项  

        // 获取并显示页面  
        $this->showDateSortedPages($ns, $offset, $limit);  
    }  

    /**  
     * 获取按日期排序的页面并显示  
     */  
    private function showDateSortedPages($ns, $offset, $limit) {  
        global $conf, $lang;  

        // 方法1: 使用search函数  
        $pages = array();  
        search($pages, $conf['datadir'], 'search_allpages', array('ns' => $ns), '', 'date');  

        // 应用权限过滤  
        $filtered = array();  
        foreach($pages as $page) {  
            if(auth_quickaclcheck($page['id']) >= AUTH_READ && !isHiddenPage($page['id'])) {  
                $filtered[] = $page;  
            }  
        }  

        // 计算分页信息  
        $total = count($filtered);  
        $hasNext = ($offset + $limit < $total);  
        $hasPrev = ($offset > 0);  

        // 获取当前页的数据  
        $currentPageData = array_slice($filtered, $offset, $limit);  

        // 输出HTML  
        echo '<div class="datepages">';  
        echo '<h1>' . sprintf($lang['datepages_title'] ?? 'Pages in namespace "%s" sorted by date', hsc($ns)) . '</h1>';  

        if(count($currentPageData) > 0) {  
            echo '<ul class="datepages-list">';  
            foreach($currentPageData as $item) {  
                $date = dformat($item['mtime']);  
                echo '<li>';  
                echo '<div class="datepages-date">' . $date . '</div>';  
                echo '<div class="datepages-page">' . html_wikilink($item['id']) . '</div>';  
                echo '</li>';  
            }  
            echo '</ul>';  

            // 分页导航  
            echo '<div class="datepages-pagination">';  
            if($hasPrev) {  
                $prevOffset = max(0, $offset - $limit);  
                echo '<a href="' . wl($INFO['id'], array('do' => 'datepages', 'ns' => $ns, 'offset' => $prevOffset, 'limit' => $limit)) . '" class="datepages-prev">' . $lang['btn_newer'] . '</a>';  
            }  

            if($hasNext) {  
                $nextOffset = $offset + $limit;  
                echo '<a href="' . wl($INFO['id'], array('do' => 'datepages', 'ns' => $ns, 'offset' => $nextOffset, 'limit' => $limit)) . '" class="datepages-next">' . $lang['btn_older'] . '</a>';  
            }  
            echo '</div>';  
        } else {  
            echo '<div class="nothing">' . $lang['nothingfound'] . '</div>';  
        }  
        echo '</div>';  
    }  
}

3. 可选:添加语法插件支持

如果您希望通过语法标记来调用此功能,可以添加syntax.php

<?php  
/**  
 * DokuWiki Plugin datepages (Syntax Component)  
 *  
 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html  
 * @author  Your Name  
 */  

class syntax_plugin_datepages extends DokuWiki_Syntax_Plugin {  

    public function getType() {  
        return 'substition';  
    }  

    public function getPType() {  
        return 'block';  
    }  

    public function getSort() {  
        return 155;  
    }  

    public function connectTo($mode) {  
        $this->Lexer->addSpecialPattern('{{datepages(?:\?[^}]*)?}}', $mode, 'plugin_datepages');  
    }  

    public function handle($match, $state, $pos, Doku_Handler $handler) {  
        $match = substr($match, 11, -2); // 去除 {{datepages 和 }}  

        // 解析参数  
        $params = array();  
        if(substr($match, 0, 1) == '?') {  
            $match = substr($match, 1);  
            parse_str($match, $params);  
        }  

        return $params;  
    }  

    public function render($mode, Doku_Renderer $renderer, $data) {  
        if($mode != 'xhtml') return false;  

        global $INFO;  

        // 设置默认参数  
        $ns = $data['ns'] ?? getNS($INFO['id']);  
        $limit = (int)($data['limit'] ?? 10);  
        $offset = (int)($data['offset'] ?? 0);  

        // 获取页面  
        $pages = array();  
        search($pages, $GLOBALS['conf']['datadir'], 'search_allpages', array('ns' => $ns), '', 'date');  

        // 应用权限过滤  
        $filtered = array();  
        foreach($pages as $page) {  
            if(auth_quickaclcheck($page['id']) >= AUTH_READ && !isHiddenPage($page['id'])) {  
                $filtered[] = $page;  
            }  
        }  

        // 计算分页信息  
        $total = count($filtered);  
        $hasNext = ($offset + $limit < $total);  
        $hasPrev = ($offset > 0);  

        // 获取当前页的数据  
        $currentPageData = array_slice($filtered, $offset, $limit);  

        // 输出HTML  
        $renderer->doc .= '<div class="datepages">';  

        if(count($currentPageData) > 0) {  
            $renderer->doc .= '<ul class="datepages-list">';  
            foreach($currentPageData as $item) {  
                $date = dformat($item['mtime']);  
                $renderer->doc .= '<li>';  
                $renderer->doc .= '<div class="datepages-date">' . $date . '</div>';  
                $renderer->doc .= '<div class="datepages-page">';  
                $renderer->internallink($item['id']);  
                $renderer->doc .= '</div>';  
                $renderer->doc .= '</li>';  
            }  
            $renderer->doc .= '</ul>';  

            // 分页导航  
            $renderer->doc .= '<div class="datepages-pagination">';  
            if($hasPrev) {  
                $prevOffset = max(0, $offset - $limit);  
                $params = array('ns' => $ns, 'offset' => $prevOffset, 'limit' => $limit);  
                $renderer->doc .= '<a href="' . wl($INFO['id'], array('do' => 'datepages') + $params) . '" class="datepages-prev">' . $lang['btn_newer'] . '</a>';  
            }  

            if($hasNext) {  
                $nextOffset = $offset + $limit;  
                $params = array('ns' => $ns, 'offset' => $nextOffset, 'limit' => $limit);  
                $renderer->doc .= '<a href="' . wl($INFO['id'], array('do' => 'datepages') + $params) . '" class="datepages-next">' . $lang['btn_older'] . '</a>';  
            }  
            $renderer->doc .= '</div>';  
        } else {  
            $renderer->doc .= '<div class="nothing">' . $lang['nothingfound'] . '</div>';  
        }  
        $renderer->doc .= '</div>';  

        return true;  
    }  
}

4. 添加样式(可选)

创建style.css文件:

.datepages {  
    margin: 1em 0;  
}  

.datepages-list {  
    list-style: none;  
    padding: 0;  
}  

.datepages-list li {  
    margin-bottom: 0.5em;  
    padding: 0.5em;  
    border-bottom: 1px solid #eee;  
    display: flex;  
}  

.datepages-date {  
    flex: 0 0 150px;  
    color: #666;  
}  

.datepages-page {  
    flex: 1;  
}  

.datepages-pagination {  
    margin-top: 1em;  
    display: flex;  
    justify-content: space-between;  
}

使用方法

方法1:通过URL参数

访问以下URL来查看按日期排序的页面:

https://your-wiki.com/doku.php?do=datepages&ns=namespace&offset=0&limit=10

方法2:通过语法标记(如果实现了syntax.php)

在wiki页面中添加以下语法:

{{datepages?ns=namespace&limit=10&offset=0}}

使用索引器的替代实现

如果您希望使用索引器来提高性能,可以替换showDateSortedPages方法中的页面获取部分:

private function showDateSortedPages($ns, $offset, $limit) {  
    global $conf, $lang;  

    // 使用索引器获取页面  
    $Indexer = idx_get_indexer();  
    $allPages = $Indexer->getPages();  

    // 过滤命名空间  
    $nsPages = array();  
    foreach($allPages as $id => $title) {  
        if(getNS($id) == $ns) {  
            $nsPages[$id] = $title;  
        }  
    }  

    // 按修改时间排序  
    $pageIds = array_keys($nsPages);  
    usort($pageIds, 'ft_pagemtimesorter');  

    // 应用权限过滤  
    $filtered = array();  
    foreach($pageIds as $id) {  
        if(auth_quickaclcheck($id) >= AUTH_READ && !isHiddenPage($id) && page_exists($id)) {  
            $meta = p_get_metadata($id);  
            $filtered[] = array(  
                'id' => $id,  
                'title' => $nsPages[$id],  
                'mtime' => filemtime(wikiFN($id))  
            );  
        }  
    }  

    // 计算分页信息  
    $total = count($filtered);  
    $hasNext = ($offset + $limit < $total);  
    $hasPrev = ($offset > 0);  

    // 获取当前页的数据  
    $currentPageData = array_slice($filtered, $offset, $limit);  

    // 输出HTML  
    // ... 与之前相同 ...  
}

结论

对于按日期排序并分页显示命名空间下页面的功能,自定义action方法是最合适的实现方式。这种方法可以:

  1. 处理URL参数和分页
  2. 提供更灵活的页面展示
  3. 与DokuWiki的现有机制更好地集成

如果您希望在页面内嵌入此功能,可以同时实现语法插件部分。两种方法可以共存,为用户提供更多的使用选择。

Notes

这个实现基于DokuWiki的核心功能,包括search()函数和索引器。对于大型wiki站点,建议使用索引器方法以提高性能。代码中的分页逻辑参考了DokuWiki的Recent类的实现方式,确保与系统的其他部分保持一致的用户体验。

如果您需要更复杂的排序或过滤功能,可以扩展此插件,添加更多参数和选项。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇