PageRenderTime 43ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/plugin/pcomment.inc.php

https://github.com/miya5n/pukiwiki
PHP | 370 lines | 271 code | 65 blank | 34 comment | 80 complexity | 886eb6a241f2d5f05fde84602fdeecd8 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. // PukiWiki - Yet another WikiWikiWeb clone
  3. // $Id: pcomment.inc.php,v 1.48 2011/01/25 15:01:01 henoheno Exp $
  4. //
  5. // Page comment plugin - Show/Insert comments into another page
  6. //
  7. // Usage: #pcomment([page][,max][,options])
  8. //
  9. // page -- An another page-name that holds comments
  10. // (default:PLUGIN_PCOMMENT_PAGE)
  11. // max -- Max number of recent comments to show
  12. // (0:Show all, default:PLUGIN_PCOMMENT_NUM_COMMENTS)
  13. //
  14. // Options:
  15. // above -- Comments are listed above the #pcomment (added by chronological order)
  16. // below -- Comments are listed below the #pcomment (by reverse order)
  17. // reply -- Show radio buttons allow to specify where to reply
  18. // Default recording page name (%s = $vars['page'] = original page name)
  19. switch (LANG) {
  20. case 'ja': define('PLUGIN_PCOMMENT_PAGE', '[[コメント/%s]]'); break;
  21. default: define('PLUGIN_PCOMMENT_PAGE', '[[Comments/%s]]'); break;
  22. }
  23. define('PLUGIN_PCOMMENT_NUM_COMMENTS', 10); // Default 'latest N posts'
  24. define('PLUGIN_PCOMMENT_DIRECTION_DEFAULT', 1); // 1: above 0: below
  25. define('PLUGIN_PCOMMENT_SIZE_MSG', 70);
  26. define('PLUGIN_PCOMMENT_SIZE_NAME', 15);
  27. // Auto log rotation
  28. define('PLUGIN_PCOMMENT_AUTO_LOG', 0); // 0:off 1-N:number of comments per page
  29. // Update recording page's timestamp instead of parent's page itself
  30. define('PLUGIN_PCOMMENT_TIMESTAMP', 0);
  31. // ----
  32. define('PLUGIN_PCOMMENT_FORMAT_NAME', '[[$name]]');
  33. define('PLUGIN_PCOMMENT_FORMAT_MSG', '$msg');
  34. define('PLUGIN_PCOMMENT_FORMAT_NOW', '&new{$now};');
  35. // "\x01", "\x02", "\x03", and "\x08" are used just as markers
  36. define('PLUGIN_PCOMMENT_FORMAT_STRING',
  37. "\x08" . 'MSG' . "\x08" . ' -- ' . "\x08" . 'NAME' . "\x08" . ' ' . "\x08" . 'DATE' . "\x08");
  38. function plugin_pcomment_action()
  39. {
  40. global $vars;
  41. if (PKWK_READONLY) die_message('PKWK_READONLY prohibits editing');
  42. if (! isset($vars['msg']) || $vars['msg'] == '') return array();
  43. $refer = isset($vars['refer']) ? $vars['refer'] : '';
  44. $retval = plugin_pcomment_insert();
  45. if ($retval['collided']) {
  46. $vars['page'] = $refer;
  47. return $retval;
  48. }
  49. pkwk_headers_sent();
  50. header('Location: ' . get_script_uri() . '?' . rawurlencode($refer));
  51. exit;
  52. }
  53. function plugin_pcomment_convert()
  54. {
  55. global $vars;
  56. global $_pcmt_messages;
  57. $params = array(
  58. 'noname'=>FALSE,
  59. 'nodate'=>FALSE,
  60. 'below' =>FALSE,
  61. 'above' =>FALSE,
  62. 'reply' =>FALSE,
  63. '_args' =>array()
  64. );
  65. foreach(func_get_args() as $arg)
  66. plugin_pcomment_check_arg($arg, $params);
  67. $vars_page = isset($vars['page']) ? $vars['page'] : '';
  68. $page = (isset($params['_args'][0]) && $params['_args'][0] != '') ? $params['_args'][0] :
  69. sprintf(PLUGIN_PCOMMENT_PAGE, strip_bracket($vars_page));
  70. $count = isset($params['_args'][1]) ? intval($params['_args'][1]) : 0;
  71. if ($count == 0) $count = PLUGIN_PCOMMENT_NUM_COMMENTS;
  72. $_page = get_fullname(strip_bracket($page), $vars_page);
  73. if (!is_pagename($_page))
  74. return sprintf($_pcmt_messages['err_pagename'], htmlsc($_page));
  75. $dir = PLUGIN_PCOMMENT_DIRECTION_DEFAULT;
  76. if ($params['below']) {
  77. $dir = 0;
  78. } elseif ($params['above']) {
  79. $dir = 1;
  80. }
  81. list($comments, $digest) = plugin_pcomment_get_comments($_page, $count, $dir, $params['reply']);
  82. if (PKWK_READONLY) {
  83. $form_start = $form = $form_end = '';
  84. } else {
  85. // Show a form
  86. if ($params['noname']) {
  87. $title = $_pcmt_messages['msg_comment'];
  88. $name = '';
  89. } else {
  90. $title = $_pcmt_messages['btn_name'];
  91. $name = '<input type="text" name="name" size="' . PLUGIN_PCOMMENT_SIZE_NAME . '" />';
  92. }
  93. $radio = $params['reply'] ?
  94. '<input type="radio" name="reply" value="0" tabindex="0" checked="checked" />' : '';
  95. $comment = '<input type="text" name="msg" size="' . PLUGIN_PCOMMENT_SIZE_MSG . '" />';
  96. $s_page = htmlsc($page);
  97. $s_refer = htmlsc($vars_page);
  98. $s_nodate = htmlsc($params['nodate']);
  99. $form_start = '<form action="' . get_script_uri() . '" method="post">' . "\n";
  100. $form = <<<EOD
  101. <div>
  102. <input type="hidden" name="digest" value="$digest" />
  103. <input type="hidden" name="plugin" value="pcomment" />
  104. <input type="hidden" name="refer" value="$s_refer" />
  105. <input type="hidden" name="page" value="$s_page" />
  106. <input type="hidden" name="nodate" value="$s_nodate" />
  107. <input type="hidden" name="dir" value="$dir" />
  108. <input type="hidden" name="count" value="$count" />
  109. $radio $title $name $comment
  110. <input type="submit" value="{$_pcmt_messages['btn_comment']}" />
  111. </div>
  112. EOD;
  113. $form_end = '</form>' . "\n";
  114. }
  115. if (! is_page($_page)) {
  116. $link = make_pagelink($_page);
  117. $recent = $_pcmt_messages['msg_none'];
  118. } else {
  119. $msg = ($_pcmt_messages['msg_all'] != '') ? $_pcmt_messages['msg_all'] : $_page;
  120. $link = make_pagelink($_page, $msg);
  121. $recent = ! empty($count) ? sprintf($_pcmt_messages['msg_recent'], $count) : '';
  122. }
  123. if ($dir) {
  124. return '<div>' .
  125. '<p>' . $recent . ' ' . $link . '</p>' . "\n" .
  126. $form_start .
  127. $comments . "\n" .
  128. $form .
  129. $form_end .
  130. '</div>' . "\n";
  131. } else {
  132. return '<div>' .
  133. $form_start .
  134. $form .
  135. $comments. "\n" .
  136. $form_end .
  137. '<p>' . $recent . ' ' . $link . '</p>' . "\n" .
  138. '</div>' . "\n";
  139. }
  140. }
  141. function plugin_pcomment_insert()
  142. {
  143. global $vars, $now, $_title_updated, $_no_name, $_pcmt_messages;
  144. $refer = isset($vars['refer']) ? $vars['refer'] : '';
  145. $page = isset($vars['page']) ? $vars['page'] : '';
  146. $page = get_fullname($page, $refer);
  147. if (! is_pagename($page))
  148. return array(
  149. 'msg' =>'Invalid page name',
  150. 'body'=>'Cannot add comment' ,
  151. 'collided'=>TRUE
  152. );
  153. check_editable($page, true, true);
  154. $ret = array('msg' => $_title_updated, 'collided' => FALSE);
  155. $msg = str_replace('$msg', rtrim($vars['msg']), PLUGIN_PCOMMENT_FORMAT_MSG);
  156. $name = (! isset($vars['name']) || $vars['name'] == '') ? $_no_name : $vars['name'];
  157. $name = ($name == '') ? '' : str_replace('$name', $name, PLUGIN_PCOMMENT_FORMAT_NAME);
  158. $date = (! isset($vars['nodate']) || $vars['nodate'] != '1') ?
  159. str_replace('$now', $now, PLUGIN_PCOMMENT_FORMAT_NOW) : '';
  160. if ($date != '' || $name != '') {
  161. $msg = str_replace("\x08" . 'MSG' . "\x08", $msg, PLUGIN_PCOMMENT_FORMAT_STRING);
  162. $msg = str_replace("\x08" . 'NAME' . "\x08", $name, $msg);
  163. $msg = str_replace("\x08" . 'DATE' . "\x08", $date, $msg);
  164. }
  165. $reply_hash = isset($vars['reply']) ? $vars['reply'] : '';
  166. if ($reply_hash || ! is_page($page)) {
  167. $msg = preg_replace('/^\-+/', '', $msg);
  168. }
  169. $msg = rtrim($msg);
  170. if (! is_page($page)) {
  171. $postdata = '[[' . htmlsc(strip_bracket($refer)) . ']]' . "\n\n" .
  172. '-' . $msg . "\n";
  173. } else {
  174. $postdata = get_source($page);
  175. $count = count($postdata);
  176. $digest = isset($vars['digest']) ? $vars['digest'] : '';
  177. if (md5(join('', $postdata)) !== $digest) {
  178. $ret['msg'] = $_pcmt_messages['title_collided'];
  179. $ret['body'] = $_pcmt_messages['msg_collided'];
  180. }
  181. $start_position = 0;
  182. while ($start_position < $count) {
  183. if (preg_match('/^\-/', $postdata[$start_position])) break;
  184. ++$start_position;
  185. }
  186. $end_position = $start_position;
  187. $dir = isset($vars['dir']) ? $vars['dir'] : '';
  188. // Find the comment to reply
  189. $level = 1;
  190. $b_reply = FALSE;
  191. if ($reply_hash != '') {
  192. while ($end_position < $count) {
  193. $matches = array();
  194. if (preg_match('/^(\-{1,2})(?!\-)(.*)$/', $postdata[$end_position++], $matches)
  195. && md5($matches[2]) === $reply_hash)
  196. {
  197. $b_reply = TRUE;
  198. $level = strlen($matches[1]) + 1;
  199. while ($end_position < $count) {
  200. if (preg_match('/^(\-{1,3})(?!\-)/', $postdata[$end_position], $matches)
  201. && strlen($matches[1]) < $level) break;
  202. ++$end_position;
  203. }
  204. break;
  205. }
  206. }
  207. }
  208. if ($b_reply == FALSE)
  209. $end_position = ($dir == '0') ? $start_position : $count;
  210. // Insert new comment
  211. array_splice($postdata, $end_position, 0, str_repeat('-', $level) . $msg . "\n");
  212. if (PLUGIN_PCOMMENT_AUTO_LOG) {
  213. $_count = isset($vars['count']) ? $vars['count'] : '';
  214. plugin_pcomment_auto_log($page, $dir, $_count, $postdata);
  215. }
  216. $postdata = join('', $postdata);
  217. }
  218. page_write($page, $postdata, PLUGIN_PCOMMENT_TIMESTAMP);
  219. if (PLUGIN_PCOMMENT_TIMESTAMP) {
  220. if ($refer != '') pkwk_touch_file(get_filename($refer));
  221. put_lastmodified();
  222. }
  223. return $ret;
  224. }
  225. // Auto log rotation
  226. function plugin_pcomment_auto_log($page, $dir, $count, & $postdata)
  227. {
  228. if (! PLUGIN_PCOMMENT_AUTO_LOG) return;
  229. $keys = array_keys(preg_grep('/(?:^-(?!-).*$)/m', $postdata));
  230. if (count($keys) < (PLUGIN_PCOMMENT_AUTO_LOG + $count)) return;
  231. if ($dir) {
  232. // Top N comments (N = PLUGIN_PCOMMENT_AUTO_LOG)
  233. $old = array_splice($postdata, $keys[0], $keys[PLUGIN_PCOMMENT_AUTO_LOG] - $keys[0]);
  234. } else {
  235. // Bottom N comments
  236. $old = array_splice($postdata, $keys[count($keys) - PLUGIN_PCOMMENT_AUTO_LOG]);
  237. }
  238. // Decide new page name
  239. $i = 0;
  240. do {
  241. ++$i;
  242. $_page = $page . '/' . $i;
  243. } while (is_page($_page));
  244. page_write($_page, '[[' . $page . ']]' . "\n\n" . join('', $old));
  245. // Recurse :)
  246. plugin_pcomment_auto_log($page, $dir, $count, $postdata);
  247. }
  248. // Check arguments
  249. function plugin_pcomment_check_arg($val, & $params)
  250. {
  251. if ($val != '') {
  252. $l_val = strtolower($val);
  253. foreach (array_keys($params) as $key) {
  254. if (strpos($key, $l_val) === 0) {
  255. $params[$key] = TRUE;
  256. return;
  257. }
  258. }
  259. }
  260. $params['_args'][] = $val;
  261. }
  262. function plugin_pcomment_get_comments($page, $count, $dir, $reply)
  263. {
  264. global $_msg_pcomment_restrict;
  265. if (! check_readable($page, false, false))
  266. return array(str_replace('$1', $page, $_msg_pcomment_restrict));
  267. $reply = (! PKWK_READONLY && $reply); // Suprress radio-buttons
  268. $data = get_source($page);
  269. $data = preg_replace('/^#pcomment\(?.*/i', '', $data); // Avoid eternal recurse
  270. if (! is_array($data)) return array('', 0);
  271. $digest = md5(join('', $data));
  272. // Get latest N comments
  273. $num = $cnt = 0;
  274. $cmts = $matches = array();
  275. if ($dir) $data = array_reverse($data);
  276. foreach ($data as $line) {
  277. if ($count > 0 && $dir && $cnt == $count) break;
  278. if (preg_match('/^(\-{1,2})(?!\-)(.+)$/', $line, $matches)) {
  279. if ($count > 0 && strlen($matches[1]) == 1 && ++$cnt > $count) break;
  280. // Ready for radio-buttons
  281. if ($reply) {
  282. ++$num;
  283. $cmts[] = $matches[1] . "\x01" . $num . "\x02" .
  284. md5($matches[2]) . "\x03" . $matches[2] . "\n";
  285. continue;
  286. }
  287. }
  288. $cmts[] = $line;
  289. }
  290. $data = $cmts;
  291. if ($dir) $data = array_reverse($data);
  292. unset($cmts, $matches);
  293. // Remove lines before comments
  294. while (! empty($data) && substr($data[0], 0, 1) != '-')
  295. array_shift($data);
  296. $comments = convert_html($data);
  297. unset($data);
  298. // Add radio buttons
  299. if ($reply)
  300. $comments = preg_replace('/<li>' . "\x01" . '(\d+)' . "\x02" . '(.*)' . "\x03" . '/',
  301. '<li class="pcmt"><input class="pcmt" type="radio" name="reply" value="$2" tabindex="$1" />',
  302. $comments);
  303. return array($comments, $digest);
  304. }
  305. ?>