信步漫谈之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
    1. 打开 /etc/selinux/config 文件
    SELINUX=enforcing
    修改为
    SELINUX=disabled
    
    1. 重启服务器生效

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),并根据提示进行安装配置
    1. 右上角选择语言
    2. 填写维基名称、用户、密码、邮箱
    3. 选择“初始的 ACL 政策”为“任何人都有读权限,只有注册用户有写和上传权限”
    4. 保存,完成安装
  • 统一编码
    1. 查看当前系统编码(命令:locale),此处查看是 UTF-8
    2. 打开 wiki/conf/local.php 文件
    3. 在最后一行加上编码配置
    $conf['fnencode']='utf-8';
    

6 DokuWiki 使用方式

7 DokuWiki 插件优化

  • 导航栏添加树形风格,指定新增词条的命名空间
    1. 新增页面插件(Add New Page)
    2. 导航菜单插件(IndexMenu Plugin)
      • 新建wiki/data/pages/sidebar.txt,内容如下
      ===== 导航目录 =====
      {{indexmenu>..|navbar}}
      ===== 添加新页面 =====
      {{NEWPAGE}}
      
  • 兼容 markdown 语法
    1. Markdown插件(Markdown Page Plugin)
    2. 安装插件后,在新增编辑词条时,<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>
    ",'',$attrs['_text']);
    	$text = str_replace("
    </markdown>",'',$text);
    	return '<div id="editormd" contenteditable="true"><textarea name="wikitext">'.DOKU_LF.formText($text).'</textarea></div>';
    }
    
  • 修改 wiki/inc/parser/xhtml.php 里的函数 cdata
    function cdata($text) {
    	//$this->doc .= $this->_xmlEntities($text);
    	return $this->doc.=$text;
    }
    
    修改原因:因为以前是纯字符编辑器,会将一些特殊符号进行过滤,比如:<>等等.而替换之后的xheditor本身已经做了一次过滤了,再次过滤就会导致字符<变成&lt,因此去掉这段之后,就只过滤一次
  • 修改 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>
    ".$TEXT."
    </markdown>",$SUF,true),$SUM,$INPUT->bool('minor')); //use pretty mode for con
    
  • 修改 wiki/lib/tpl/dokuwiki/main.php,添加 editor.md 包
    1. head 节点中添加
    <link rel="stylesheet" href="<?php echo DOKU_BASE;?>lib/editor.md/css/editormd.min.css" />
    
    1. 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", {
    			 "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("
    ![](" + 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?
    
    原因:
    1. SELinux没有关闭
    2. 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

11 参考资料(感谢)

原文地址:https://www.cnblogs.com/alfredinchange/p/14401742.html