WordPress → DokuWiki 自动同步教程(同服务器)

WordPress → DokuWiki 自动同步教程(同服务器|模式A纯文本,去除HTML标签)

版本:模式 A【纯文本模式,自动剥离全部 HTML 标签】

 

方案特点:
不走 DokuWiki API/RPC,直接操作服务器 txt 物理文件
✅ DokuWiki 首页列表显示中文文章标题(读取页面 H1,不是文件名)
✅ 文件名固定 post_文章ID.txt,彻底解决中文标题乱命名、1.txt 异常问题
自动剥离 WP 文章所有 HTML 标签,DokuWiki 页面只展示干净纯文本,不会输出代码标签
✅ 新增 / 修改 / 删除 WP 文章,DokuWiki 索引列表自动刷新,删除后条目立刻消失
✅ 保留完整缓存自动清理,双重兜底防缓存残留
✅ 所有操作在 WordPress 侧触发,无需手动在 Doku 后台操作

一、环境与插件准备(WordPress 端)

  1. 必备插件:Code Snippets

作用:在 WP 后台直接注入 PHP 代码,不用修改主题functions.php,升级主题不会丢失代码。

  1. WP 后台 → 插件 → 安装插件
  2. 搜索 Code Snippets,安装并启用
地址:WP 官方插件库直接搜索即可

 

可选:WP 日志查看插件(如 WP Log Viewer),方便看代码error_log调试信息。

二、DokuWiki 端准备

  1. 安装 IndexMenu 插件
作用:在 Doku 首页生成文章列表,读取页面内 H1 标题展示中文名称(核心!实现文件名是英文 post_xx,前端显示中文标题)
  1. DokuWiki 后台 → 插件管理器(Extension Manager)
  2. 搜索 IndexMenu,在线安装
  3. 确认插件启用
  4. 创建命名空间 wp
  5. 访问 Doku,新建页面:wp:start
  6. 在页面内粘贴下面代码(开启页面无缓存 + IndexMenu 渲染列表
Plain
~~NOCACHE~~
{{indexmenu>wp#1|-h1 noself sort=mtime sortdir=desc}}
  • ~~NOCACHE~~:强制每次打开这个页面实时渲染,作为缓存兜底保险
  • indexmenu>wp#1:扫描 wp 命名空间下一级页面
  • -h1:读取页面内部 H1 标题作为列表显示文字(最关键参数)
  • noself:不显示 wp:start 自身
  • sort=mtime:按文章修改时间排序
  • sortdir=desc:新文章排在最上面
保存页面,Doku 访问地址示例:https://你的wiki域名/doku.php?id=wp

 

  1. 服务器目录权限(非常关键!)

路径:/www/wwwroot/htdocs/addons/wiki/data/
需要保证 PHP 运行用户(一般是www用户)拥有下面目录读写 + 删除权限

  1. data/pages/wp/:创建、写入、删除 txt 页面文件
  2. data/meta/wp/:创建、写入、删除 meta 元数据文件
  3. data/cache/ + data/cache/indexmenu/:删除缓存文件(解决删除文章列表残留)

推荐权限设置(BT 面板终端执行)

bash
chown -R www:www /www/wwwroot/htdocs/addons/wiki/data
chmod -R 755 /www/wwwroot/htdocs/addons/wiki/data

三、WordPress Code Snippets 代码部署(模式 A:纯文本,去除 HTML 标签)

  1. WP 后台 → Snippets → Add New
  2. 名称:WP同步DokuWiki(本地直写postID命名|模式A纯文本,清除HTML)
  3. 粘贴下面完整代码
  4. 选择:Run snippet everywhere(全站生效)
  5. 保存并启用
php
<?php
/**
* WP同步DokuWiki【本地直写文件版,无RPC|模式A:纯文本模式,自动清除HTML标签】
* 固定post_文章ID生成文件名,页面内保留中文H1标题,IndexMenu读取H1展示中文目录
* 自动清理页面缓存、wp:start索引缓存、IndexMenu插件缓存;删除文章索引条目自动消失
*/
add_action('save_post', 'wp_save_to_dokuwiki_file', 20, 2);
add_action('before_delete_post', 'wp_delete_dokuwiki_file');function wp_save_to_dokuwiki_file($post_id, $post) {
// ======================【配置区,请核对服务器路径】======================
$wiki_root = '/www/wwwroot/htdocs/addons/wiki/'; //DokuWiki根目录,末尾带斜杠
$wiki_page_root = $wiki_root . 'data/pages/wp/';
$wiki_meta_root = $wiki_root . 'data/meta/wp/';
$wiki_cache_root = $wiki_root . 'data/cache/';
// =================================================================
// 跳过自动保存、修订、非文章类型、草稿
if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) return;
if ($post->post_type !== 'post') return;
if ($post->post_status !== 'publish') return;

$raw_title = trim(html_entity_decode($post->post_title));

// 固定使用文章ID生成页面文件名,不再用标题处理,彻底杜绝文件名异常
$pagename = 'post_'.$post_id;

$file_path = $wiki_page_root . $pagename . '.txt';
$meta_path = $wiki_meta_root . $pagename . '.meta';
// ============【核心:strip_tags清除全部HTML标签,只保留纯文字】============
$clean_content = strip_tags($post->post_content);
$wiki_content = "====== {$raw_title} ======\n\n" . $clean_content;

// 自动创建wp目录(不存在时)
if (!file_exists($wiki_page_root)) {
mkdir($wiki_page_root, 0755, true);
}
if (!file_exists($wiki_meta_root)) {
mkdir($wiki_meta_root, 0755, true);
}

// 写入页面txt
$write_result = file_put_contents($file_path, $wiki_content);
if ($write_result === false) {
error_log("DokuWiki页面写入失败:{$file_path},检查目录权限");
return;
}

// 写入meta元信息,用于IndexMenu按修改时间排序
$now = time();
$meta_data = [
'lastmod' => $now,
'date'    => $now,
'user'    => '',
'ip'      => '',
'sum'     => md5($wiki_content),
'size'    => strlen($wiki_content),
];
$meta_text = serialize($meta_data);
file_put_contents($meta_path, $meta_text);

// ==========【缓存清理核心代码:解决索引列表不刷新、删除残留】==========
// 1. 删除当前文章页面缓存
$cache_file = $wiki_cache_root . 'wiki_' . md5("wp:{$pagename}") . '.cache';
if(file_exists($cache_file)) unlink($cache_file);
// 2. 删除 wp:start 索引主页渲染缓存(核心,清除旧列表渲染结果)
$start_cache = $wiki_cache_root . 'wiki_' . md5("wp:start") . '.cache';
if(file_exists($start_cache)) unlink($start_cache);
// 3. 清空IndexMenu插件自身命名空间树缓存
$index_cache_dir = $wiki_cache_root . 'indexmenu/';
if(is_dir($index_cache_dir)){
$files = glob($index_cache_dir . '*');
if(is_array($files)){ //防止空目录glob返回false产生PHP警告
foreach ($files as $f) {
if(is_file($f)) unlink($f);
}
}
}
// ==============================================================
error_log("DokuWiki同步成功 | pageid:wp:{$pagename} | 原文标题:{$raw_title}");
}

// 删除WP文章,同步删除DokuWiki页面文件、meta文件、全部相关缓存
function wp_delete_dokuwiki_file($post_id){
$post = get_post($post_id);
if (!$post || $post->post_type !== 'post') return;

$wiki_root = '/www/wwwroot/htdocs/addons/wiki/';
$wiki_page_root = $wiki_root . 'data/pages/wp/';
$wiki_meta_root = $wiki_root . 'data/meta/wp/';
$wiki_cache_root = $wiki_root . 'data/cache/';

$raw_title = trim(html_entity_decode($post->post_title));
// 和保存函数保持一致:固定post_文章ID命名
$pagename = 'post_'.$post_id;

$file_path = $wiki_page_root . $pagename . '.txt';
$meta_path = $wiki_meta_root . $pagename . '.meta';
$cache_file = $wiki_cache_root . 'wiki_' . md5("wp:{$pagename}") . '.cache';

// 删除页面本体、meta
if(file_exists($file_path)) unlink($file_path);
if(file_exists($meta_path)) unlink($meta_path);
if(file_exists($cache_file)) unlink($cache_file);

// 清理wp:start索引页面缓存
$start_cache = $wiki_cache_root . 'wiki_' . md5("wp:start") . '.cache';
if(file_exists($start_cache)) unlink($start_cache);

// 清空IndexMenu缓存
$index_cache_dir = $wiki_root . 'data/cache/indexmenu/';
if(is_dir($index_cache_dir)){
$files = glob($index_cache_dir . '*');
if(is_array($files)){
foreach ($files as $f) {
if(is_file($f)) unlink($f);
}
}
}
error_log("DokuWiki页面已删除 wp:{$pagename}");
}

 

⚠️ 重点:修改代码第一部分$wiki_root路径,和你服务器实际 Doku 根目录保持一致!

四、测试流程(一步一步验证)

  1. 进入 WP 后台 → Code Snippets,停用旧版本代码片段,启用上面新模式 A 代码
  2. 在 WordPress 新建一篇文章,发布
  3. 打开服务器目录 /wiki/data/pages/wp/,看到生成 txt
  4. 打开 Doku 的 wp 页面,列表出现中文标题,文章内容为纯文本,不再出现 HTML 标签代码
  5. 在 WP 编辑修改文章并更新 → Doku 内容更新
  6. 在 WP 后台删除该文章
  7. 服务器上txt自动消失,Doku wp 页面刷新,这条条目直接消失
⚠️ 重要:已经同步完成的旧文章,需要在 WP 后台打开文章,点一次【更新】,才会重新生成清除 HTML 后的干净文本;新发布文章自动生效。
调试手段:访问 wiki 地址追加 &purge=true,强制页面清缓存:
https://你的wiki域名/doku.php?id=wp&purge=true

五、原理说明(方便后期维护)

  1. 文件名:post_文章txt,永久唯一,不受标题字符影响;
  2. HTML 处理:strip_tags() 函数自动剔除所有 HTML 标签,只保留正文文字,Doku 页面干净无代码;
  3. Doku 列表中文来源:IndexMenu -h1 参数读取 txt 文件第一行 ======文章标题======,列表展示这个中文,和文件名无关
  4. 缓存机制
  • WP 发布 / 删除文章时,PHP 自动删除:文章页面缓存 + wp:start 索引页面缓存 + IndexMenu 插件目录树缓存
  • ~~NOCACHE~~ 作为兜底,就算代码缓存清理失效,页面每次访问都会实时扫描文件;
  1. 限制说明
  • 仅同步 WP 的post类型文章(普通文章,不是 page 页面,如需同步页面,修改$post->post_type判断)
  • 只同步已发布 publish的文章,草稿、自动保存不会生成 Doku 页面
  • 直接操作 Doku 底层 txt 文件,不要在 DokuWiki 后台手动编辑 wp 命名空间下文章,会造成文件冲突。
  • 模式 A 仅输出纯文字,所有富格式(加粗、表格、图片、链接)都会被移除,只保留文字内容。

六、常见故障排查清单

现象 排查方向
WP 发布文章,服务器 wp 目录没有生成 txt 1. 核对$wiki_root路径;2. 检查 www 用户读写权限;3. 看 WP 错误日志
文件生成成功,Doku 列表看不到中文标题 1. 确认 IndexMenu 插件启用;2.indexmenu 代码必须带 -h1;3.txt 第一行======标题======不能换行 / 空格错误
WP 删除文章,Doku 列表还残留旧条目 1. 确认 www 用户有删除 cache 目录文件权限;2.wp:start 页面加上~~NOCACHE~~;3. 手动进data/cache/indexmenu删除全部缓存文件测试
旧文章依然显示 HTML 代码 旧文章需要在 WP 后台打开文章,点击【更新】,重新触发同步生成干净内容;新文章直接正常
日志报 glob 警告 代码内已增加is_array($files)判断,不会再产生警告

七、维护建议

  1. 不要在 Doku 后台手动修改wp:下面页面,所有内容由 WP 单方面管理;
  2. 定期备份 Doku data/pages/wp、data/meta/wp目录;
  3. 如果后续想要保留加粗 / 表格等排版,可以切换到【模式 B HTML 转 Doku 语法】版本;
  4. 服务器迁移时,同步修改代码里\\$wiki_root**路径,否则失效。

1789099274-WordPress → DokuWiki 自动同步教程(本地直写文件版,无RPC|IndexMenu中文标题列表,删除自动消失)

发表回复

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理