信步漫谈之Wiki知识库——搭建dokuwiki
目录
1 目标
- 搭建 DokuWiki 知识库和遇到的问题解决方式
- DokuWiki 的使用方式
- 扩展插件支持 markdown 语法
2 资源
系统:CentOS 7.7.1908-Minimal(本文服务器地址:192.168.64.100)
DokuWiki 版本:2020-07-29(下载最后稳定版路径:https://download.dokuwiki.org/src/dokuwiki/dokuwiki-stable.tgz)
PHP 版本:7.3.27
3 环境准备
- 关闭防火墙
# systemctl stop firewalld.service
# systemctl disable firewalld.service
- 启用epel和remi存储库以使用最新的PHP 7.x版本
# yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
# yum -y install epel-release
- 禁用安装php5.4以从remi存储库安装php7.3
# yum-config-manager --disable remi-php54
# yum-config-manager --enable remi-php73
- 安装 PHP
# yum -y install httpd
# yum -y install php php-gd php-xml
- 启动并启用服务
# systemctl start httpd
# systemctl enable httpd
- 重新启动Apache Web服务器
# systemctl restart httpd
- 关闭SELinux
- 打开 /etc/selinux/config 文件
SELINUX=enforcing 修改为 SELINUX=disabled
- 重启服务器生效
4 DokuWiki 安装
- 将下载的 DokuWiki 安装包上传到 /opt/dokuwiki 目录,解压到 /var/www/html 目录下,重命名为 wiki
# cd /opt/dokuwiki
# tar -zxvf dokuwiki-stable.tgz -C /var/www/html
# cd /var/www/html
# mv dokuwiki-2020-07-29/ wiki
- 修改 wiki 文件夹权限
# chown -R apache:apache wiki
- 重启 httpd 服务
# systemctl restart httpd
5 DokuWiki 初始配置
- 访问 DokuWiki 的安装程序(http://192.168.1.100/wiki/install.php),并根据提示进行安装配置
- 右上角选择语言
- 填写维基名称、用户、密码、邮箱
- 选择“初始的 ACL 政策”为“任何人都有读权限,只有注册用户有写和上传权限”
- 保存,完成安装
- 统一编码
- 查看当前系统编码(命令:locale),此处查看是 UTF-8
- 打开 wiki/conf/local.php 文件
- 在最后一行加上编码配置
$conf['fnencode']='utf-8';
6 DokuWiki 使用方式
- 插件管理
- 可登录后点击右上角的“管理”->“扩展管理器”,查看当前 DokuWiki 已安装的扩展插件,支持对现有插件的关闭/激活,联网搜索插件,下载插件包后手动安装
- 插件安装除了可通过扩展插件管理外,也可以直接下载插件压缩包,解压到 wiki/lib/plugins/ 目录下
- 新建页面
- 访问 http://地址/wiki/doku.php?id=页面名称(例如:http://192.168.1.100/wiki/doku.php?id=start)
- 提示页面不存在,右侧点击“创建该页面”,即可进入页面新增(页面支持 DokuWiki 语法)
- 添加删除导航栏
- 访问 http://地址/wiki/doku.php?id=sidebar
- 新增或编辑此项词条,该词条的内容将作为左侧导航栏展示
- 删除导航栏,可进入 wiki 安装目录,wiki/data/pages 下,删除 sidebar.txt 文件即可
- 创建命名空间
在新建页面时,访问 http://地址/wiki/doku.php?id=命名空间:页面名称,创建词条页面,同时会创建命名空间
7 DokuWiki 插件优化
- 导航栏添加树形风格,指定新增词条的命名空间
- 新增页面插件(Add New Page)
- 导航菜单插件(IndexMenu Plugin)
- 新建wiki/data/pages/sidebar.txt,内容如下
===== 导航目录 ===== {{indexmenu>..|navbar}} ===== 添加新页面 ===== {{NEWPAGE}}
- 兼容 markdown 语法
- Markdown插件(Markdown Page Plugin)
- 安装插件后,在新增编辑词条时,<markdown> 标签内的内容将按 markdown 的语法进行解析
8 完全替换为 markdown 语法编辑器
写在前面,尝试过这种完全替换为 markdown 语法编辑器的方法,并补充了原作者的一些遗漏之处,总体实现的效果还是不错的,有实时展示的编辑窗口,也支持图片上传引用。
- 下载 editor.md
- 解压到 wiki/lib/editor.md(切记,此处不是写错,是 lib 目录下,不是 lib/plugins 目录,这是个坑,我踩过。。。)
- 修改 wiki/inc/form.php 里的函数 form_wikitext($attrs),修改return结果,代码中 id="editormd" 是后面 editor.md 实例需要的 id
function form_wikitext($attrs) { // mandatory attributes unset($attrs['name']); unset($attrs['id']); $text = str_replace("<markdown>\n",'',$attrs['_text']); $text = str_replace("\n</markdown>",'',$text); return '<div id="editormd" contenteditable="true"><textarea name="wikitext">'.DOKU_LF.formText($text).'</textarea></div>'; }
- 修改 wiki/inc/parser/xhtml.php 里的函数 cdata
修改原因:因为以前是纯字符编辑器,会将一些特殊符号进行过滤,比如:<>等等.而替换之后的xheditor本身已经做了一次过滤了,再次过滤就会导致字符<变成<,因此去掉这段之后,就只过滤一次function cdata($text) { //$this->doc .= $this->_xmlEntities($text); return $this->doc.=$text; }
- 修改 wiki/inc/Action/Save.php 的以下内容
替换成saveWikiText($ID,con($PRE,$TEXT,$SUF,true),$SUM,$INPUT->bool('minor')); //use pretty mode for con
saveWikiText($ID,con($PRE,"<markdown>\n".$TEXT."\n</markdown>",$SUF,true),$SUM,$INPUT->bool('minor')); //use pretty mode for con
- 修改 wiki/lib/tpl/dokuwiki/main.php,添加 editor.md 包
- head 节点中添加
<link rel="stylesheet" href="<?php echo DOKU_BASE;?>lib/editor.md/css/editormd.min.css" />
- body 节点下添加(直接加在 <body> 的节点下方)
<script src="<?php echo DOKU_BASE;?>lib/editor.md/examples/js/jquery.min.js"></script> <script src="<?php echo DOKU_BASE;?>lib/editor.md/editormd.js"></script> <script type="text/javascript"> $ = jQuery var testEditor; $(function(md) { if (document.getElementById("editormd")) { testEditor = editormd("editormd", { width: "100%", height: 740, path: '<?php echo DOKU_BASE;?>lib/editor.md/lib/', syncScrolling : "single", imageUpload: true, imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"], imageUploadURL: "<?php echo DOKU_BASE;?>uploadimg.php", onload: function() {} }); } }); window.onload = function() { //document.getElementById("editormd").addEventListener('paste', function (event) { $("#editormd").on('paste', function(event) { //console.log(event); var items = (event.clipboardData || event.originalEvent.clipboardData).items; for (var index in items) { var item = items[index]; //console.log(item); if (item.kind === 'file') { var blob = item.getAsFile(); var reader = new FileReader(); reader.onload = function(event) { var base64 = event.target.result; console.log(base64); //ajax上传图片 $.post("<?php echo DOKU_BASE;?>uploadimg.php", { screenshots: base64 }, function(rets) { ret = JSON.parse(rets); //layer.msg(ret.msg); console.log(ret); if (ret.success === 1) { //新一行的图片显示 testEditor.insertValue("\n![](" + ret.url + ")"); } else { alert("截图上传失败:" + ret.message); } }); }; reader.readAsDataURL(blob); } } }); } </script>
- 图片上传支持
将如下代码保存到 uploadimg.php 文件,放到 wiki 根目录下,代码中添加了权限校验和兼容 dokuwiki 获取图片 url<?php if(!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__).'/'); require_once(DOKU_INC.'inc/init.php'); $INFO = pageinfo(); $hostpath=getBaseURL(false); $attachDir='/data/media/editor/';//上传文件保存路径,结尾不要带/ $maxAttachSize = 2*1024*1024; //最大上传大小,默认是2M function upEditorImg(){ global $hostpath, $attachDir, $maxAttachSize; //获取文件的大小 $file_size=$_FILES['editormd-image-file']['size']; //echo "$file_size $maxAttachSize"; if($file_size > $maxAttachSize) { echo '{"success":0,"message":"不能上传大于2M的文件"}'; return false; } //获取文件类型 $file_type=$_FILES['editormd-image-file']['type']; if($file_type!="image/jpeg" && $file_type!='image/pjpeg' && $file_type!="image/png") { echo '{"success":0,"message":"图片格式异常"}'; return false; } //判断是否上传成功(是否使用post方式上传) if(is_uploaded_file($_FILES['editormd-image-file']['tmp_name'])) { //把文件转存到你希望的目录(不要使用copy函数) $uploaded_file=$_FILES['editormd-image-file']['tmp_name']; //我们给每个用户动态的创建一个文件夹 $save_path=$_SERVER['DOCUMENT_ROOT'].$hostpath.$attachDir; //判断该用户文件夹是否已经有这个文件夹 if(!file_exists($save_path)) { mkdir($save_path); } //$move_to_file=$save_path."/".$_FILES['editormd-image-file']['name']; $file_true_name=$_FILES['editormd-image-file']['name']; $move_file_name=time().rand(1,1000).substr($file_true_name,strrpos($file_true_name,".")); $move_to_file=$save_path.$move_file_name; //echo "$uploaded_file $move_to_file"; if(move_uploaded_file($uploaded_file,iconv("utf-8","gb2312",$move_to_file))) { //echo $_FILES['editormd-image-file']['name']."上传成功"; //echo '{"success":1,"message":"上传成功", "url":"'.$hostpath.$attachDir.$move_file_name.'"}'; $result=array( 'success'=> 1, 'message'=>'上传成功', 'url'=>'editor:'.$move_file_name ); echo json_encode($result); } else { //echo "上传失败"; echo '{"success":0,"message":"服务器保存文件失败"}'; } } else { //echo "上传失败"; echo '{"success":0,"message":"上传失败"}'; return false; } } //$_POST= [screenshots] => data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAI0AAACcCAYAAABC1CibAAAL6UlEQVR4Ae2dbUiU6RrH... function upEditorScreenshots(){ global $hostpath, $attachDir, $maxAttachSize; $content = $_POST['screenshots']; if (preg_match('/^data:image\/(\w+);base64,(\S+)/', $content, $result)) { $file_type = $result[1]; $base64data = $result[2]; //echo "$file_type $base64data"; $save_path = $_SERVER['DOCUMENT_ROOT'].$hostpath.$attachDir; if (!is_dir($save_path)) { mkdir($save_path, 0777); } $filedata = base64_decode($base64data); $filename = time().rand(1,1000).".".$file_type; if (!file_put_contents($save_path . $filename, $filedata)) { echo '{"success":0,"message":"服务器保存文件失败"}'; return false; } unset($filedata); echo '{"success":1,"message":"上传成功", "url":"editor:'.$move_file_name.$filename.'"}'; return true; } else { echo '{"success":0,"message":"图片格式异常"}'; return false; } } //print_r($_POST); //print_r($_FILES); if(isset($_FILES['editormd-image-file'])){ global $INFO; if($INFO['writable'] && !$INFO['locked']) { upEditorImg(); } else { echo '{"success":0,"message":"没有权限"}'; } exit(); } if(isset($_POST['screenshots'])){ global $INFO; if($INFO['writable'] && !$INFO['locked']) { upEditorScreenshots(); } else { echo '{"success":0,"message":",没有权限"}'; } exit(); } ?>
- 修改图片加载地址
修改 wiki/lib/editor.md/lib/marked.min.js 文件中 img 标签生成的方法,在以下
代码前添加var out='<img src="'+href+'" alt="'+text+'"';
if(href.indexOf(':')>0&&href.indexOf("/")<0){href='/lib/exe/fetch.php?cache=&media='+href;}
9 遇到的问题及解决
- 安装过程提示:yum-config-manager: command not found
原因:系统默认没有安装这个命令
解决:这个命令在 yum-utils 包里,通过命令 yum -y install yum-utils 安装即可 - 访问 DokuWiki 的地址时,提示如下
原因:DokuWiki Setup Error The datadir ('pages') at ./data/pages is not found, isn't accessible or writable. You should check your config and permission settings. Or maybe you want to run the installer?
- SELinux没有关闭
- wiki 目录没有修改文件夹权限为 apache 用户
10 相关知识
- 在 DokuWiki 安装配置完成后,配置信息存放在 wiki/conf/local.php 文件中,如果语言等忘记修改,可直接修改该文件即可
<?php /** * Dokuwiki's Main Configuration File - Local Settings * Auto-generated by install script * Date: Sun, 14 Feb 2021 02:56:54 +0000 */ $conf['title'] = 'Alfred知识库'; $conf['lang'] = 'zh'; $conf['license'] = 'cc-by-sa'; $conf['useacl'] = 1; $conf['superuser'] = '@admin'; $conf['disableactions'] = 'register'; $conf['fnencode']='utf-8';
- DokuWiki 的插件官网下载地址:https://www.dokuwiki.org/plugins