/plugins/wkp_Comments.php
PHP | 354 lines | 237 code | 85 blank | 32 comment | 38 complexity | bcafdbb48420ebfe1e44a0470106235b MD5 | raw file
- <?php
- /*
- * Comments plugin for LionWiki, (c) 2009 Adam Zivner, adam.zivner@gmail.com
- *
- * There are two ways to add comments section to your pages:
- * 1) insert {plugin:COMMENTS} on appropriate place in your template
- * If you then don't want comments on some particular page, insert {NO_COMMENTS} into that page content.
- * 2) insert {COMMENTS} into your page content. Good if you want discussion only on some pages.
- *
- * Comments are almost totally templatable, see plugins/Comments/template.html, it
- * should be quite self explanatory.
- *
- * Comments are stored in var/comments/ in the same directory structure as history.
- */
- class Comments
- {
- var $desc = array(
- array("Comments", "adds support for comments.")
- );
- var $sorting_order = "asc"; // "asc" means from oldest to newest, "desc" means newest first
- var $data_dir;
- var $comments_dir;
- var $template = "template.html";
- var $rss_use = true; // turn on/off creating comments RSS
- var $rss_file;
- var $rss_max_comments = 50;
- var $rss_template = '<rss version="2.0">
- <channel>
- <title>{WIKI_TITLE}</title>
- <link>{PAGE_LINK}</link>
- <description>{WIKI_DESCRIPTION}</description>
- <language>{LANG}</language>
- {CONTENT_RSS}
- </channel>
- </rss>'; // don't change template. This exact form is needed for correct functioning.
- function Comments()
- {
- $this->data_dir = $GLOBALS["PLUGINS_DIR"] . "Comments/"; // CSS and JS for comments
- $this->comments_dir = $GLOBALS["VAR_DIR"] . "comments/"; // actual comments
- $this->rss_file = $GLOBALS["VAR_DIR"] . "comments-rss.xml";
- $this->localize();
- }
- /*
- * Process comment content, i.e. turn wiki syntax into HTML.
- *
- * Because of LionWiki core structure, we need to duplicate the functionality :(
- *
- * Supported features are: bold, italics, underscore, strikethrough, link
- */
- function processComment($txt)
- {
- global $PG_DIR;
- $txt = preg_replace("#\[([^\]\|]+)\|(\./([^\]]+)|(https?://[^\]]+))\]#U", '<a href="$2" class="external">$1</a>', $txt);
- $txt = preg_replace("#(?<!\")(https?://[^\]]+)#i", '<a href="$0" class="external">$1</a>', $txt);
- preg_match_all("/\[(?:([^|\]]+)\|)?([^\]#]+)(?:#([^\]]+))?\]/", $txt, $matches, PREG_SET_ORDER); // matching Wiki links
- foreach($matches as $m) {
- $m[1] = $m[1] ? $m[1] : $m[2]; // is page label same as its name?
- $m[3] = $m[3] ? "#".u(preg_replace("/[^\da-z]/i", "_", $m[3])) : ""; // anchor
- $attr = file_exists("$PG_DIR$m[2].txt") ? $m[3] : '&action=edit" class="pending"';
- $txt = str_replace($m[0], '<a href="'.$self.'?page='.u($m[2]).$attr.'">'.$m[1].'</a>', $txt);
- }
- $txt = preg_replace('#([0-9a-zA-Z\./~\-_]+@[0-9a-z/~\-_]+\.[0-9a-z\./~\-_]+)#i', '<a href="mailto:$0">$0</a>', $txt);
- $txt = preg_replace("/'--(.*)--'/Um", '<del>$1</del>', $txt); // strikethrough
- $txt = str_replace("--", "—", $txt); // --
- $txt = preg_replace("/'__(.*)__'/Um", '<u>$1</u>', $txt); // underlining
- $txt = preg_replace("/'''(.*)'''/Um", '<strong>$1</strong>', $txt); // bold
- $txt = preg_replace("/''(.*)''/Um", '<em>$1</em>', $txt); // italic
- $txt = preg_replace("/(\r\n|\r)/", "\n", $txt); // unifying newlines to Unix ones
- $txt = str_replace("\n", "<br />", $txt);
- return $txt;
- }
- function template()
- {
- global $CON, $html, $action, $preview, $page, $PG_DIR, $HEAD, $self, $comments_html, $comment_captcha_failed;
- /*
- * Include comments if:
- * - {plugin:COMMENTS} is in template and {NO_COMMENTS} is not in page content
- * - {COMMENTS} is in page content
- */
- if($action == "" && !$preview && ((template_match("plugin:COMMENTS", $html, $null) && strpos($CON, "{NO_COMMENTS}") === false)
- || strpos($CON, "{COMMENTS}") !== false)) {
- $HEAD .= '<script type="text/javascript" src="plugins/Comments/comments.js"></script>';
- $HEAD .= '<style type="text/css" media="all">@import url("plugins/Comments/comments.css");</style>';
- $tmpl = file_get_contents($this->data_dir . $this->template);
- $tmpl = strtr($tmpl, array(
- "{FORM_NAME}" => $this->TP_FORM_NAME,
- "{FORM_EMAIL}" => $this->TP_FORM_EMAIL,
- "{FORM_CONTENT}" => $this->TP_FORM_CONTENT,
- // Following 3 are for failed captcha test
- "{FORM_NAME_VALUE}" => $comment_captcha_failed ? h($_POST["name"]) : "",
- "{FORM_EMAIL_VALUE}" => $comment_captcha_failed ? h($_POST["email"]) : "",
- "{FORM_CONTENT_VALUE}" => $comment_captcha_failed ? h($_POST["content"]) : "",
- "{FORM_SUBMIT}" => $this->TP_FORM_SUBMIT,
- "{FORM_SELF}" => h($self),
- "{FORM_PAGE}" => h($page),
- "{COMMENTS}" => $this->TP_COMMENTS
- ));
- $items_str = "";
- if($dir = @opendir($this->comments_dir . $page)) {
- $item_tmpl = "";
- if(preg_match("/\{item\}(.*)\{\/item\}/Us", $tmpl, $m))
- $item_tmpl = $m[1];
- $filenames = array();
- while($filename = @readdir($dir))
- if(preg_match("/([0-9]{8}-[0-9]{4}-[0-9]{2})\.txt/", $filename, $m))
- $filenames[] = $filename;
- if($this->sorting_order == "asc")
- sort($filenames);
- else if($this->sorting_order == "desc")
- rsort($filenames);
- $comment_num = 0;
- foreach($filenames as $filename) {
- $comment_num++;
- $file = file_get_contents($this->comments_dir . $page . "/" . $filename);
- $delimiter = strpos($file, "\n");
- $meta = substr($file, 0, $delimiter);
- $content = substr($file, $delimiter + 1);
- list($ip, $name, $email) = explode("\t", $meta);
- $processed_content = $this->processComment($content);
- $items_str .= strtr($item_tmpl, array(
- "{CONTENT}" => $processed_content,
- "{NAME}" => h($name),
- "{EMAIL}" => h($email),
- "{NAME_TO_EMAIL}" => $email == "" ? $name : ("<a href=\"mailto:".h($email)."\">" . h($name) . "</a>"),
- "{IP}" => $ip,
- "{DATE}" => rev_time(basename($filename, ".txt")),
- "{ID}" => basename($filename, ".txt"),
- "{NUMBER}" => $comment_num,
- "{DELETE}" => h($this->TP_DELETE),
- "{DELETE_LINK}" => "$self?action=admin-deletecomment&page=" . u($page) . "&filename=" . u($filename),
- "{DELETE_CONFIRM}" => h($this->TP_DELETE_CONFIRM)
- ));
- }
- }
- $tmpl = str_replace("{NUMBER_OF_COMMENTS}", count($filenames), $tmpl);
- $comments_html = preg_replace("/\{item\}.*\{\/item\}/Us", $items_str, $tmpl);
- plugin("commentsTemplate");
- $html = template_replace("plugin:COMMENTS", $comments_html, $html);
- $CON = str_replace("{COMMENTS}", $comments_html, $CON);
- }
- $CON = str_replace("{NO_COMMENTS}", "", $CON);
- $HEAD .= "\n<link rel=\"alternate\" type=\"application/rss+xml\" title=\"RSS ".h($this->TP_COMMENTS)."\" href=\"$this->rss_file\" />\n";
- }
- function actionBegin()
- {
- global $page, $LOCAL_HOUR, $plugins, $action, $plugin_saveok, $error, $comment_captcha_failed;
- if($action == "save-comment") {
- if(isset($plugins["Captcha"]) && $plugins["Captcha"]->checkCaptcha() == true) {
- $comment_captcha_failed = true;
- $action = "";
- $error = ""; // suppress error messages
- unset($_REQUEST["qid"]); // don't check captcha again
- return true;
- }
- if(!is_dir(rtrim($this->comments_dir, "/"))) {
- mkdir(rtrim($this->comments_dir, "/"));
-
- $f = fopen($this->comments_dir . ".htaccess", "w");
- fwrite($f, "deny from all");
- fclose($f);
- }
- $c_dir = $this->comments_dir . urldecode($page);
- if(!is_dir(rtrim($c_dir, "/")))
- mkdir(rtrim($c_dir, "/"));
- function prepare($txt) {
- return strtr($txt, array(
- "\t" => "",
- "\n" => ""
- ));
- }
- $meta = prepare($_SERVER["REMOTE_ADDR"]) . "\t" . prepare($_POST["name"]) . "\t" . prepare($_POST["email"]) . "\n";
- $rightnow = date("Ymd-Hi-s", time() + $LOCAL_HOUR * 3600);
- $h = fopen($c_dir . "/" . $rightnow . ".txt", "w");
- if(!$h)
- return;
- fwrite($h, $meta . $_POST["content"]);
- fclose($h);
- $this->writeRSS($page, $rightnow, $meta . $_POST["content"]);
- header("Location: $self?page=$page#$rightnow");
- die();
- }
- }
- function writeRSS($page, $id, $content)
- {
- global $PROTECTED_READ, $WIKI_TITLE, $LANG;
- if(!$this->rss_use || $PROTECTED_READ)
- return;
- $pagelink = ($_SERVER["HTTPS"] ? "https://" : "http://") . $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["SCRIPT_NAME"];
- preg_match("/<\/language>(.*)<\/channel>/s", @file_get_contents($this->rss_file), $matches);
- $items = $matches[1];
- $pos = -1;
- // count items
- for($i = 0; $i < $this->rss_max_comments - 1; $i++)
- if(!($pos = strpos($items, "</item>", $pos + 1)))
- break;
- if($pos) // if count is higher than $max_changes - 1, cut out the rest
- $items = substr($items, 0, $pos + 7);
- $n_item = "
- <item>
- <title>".h($page)."</title>
- <pubDate>". date("r")."</pubDate>
- <link>$pagelink?page=".u($page)."#$id</link>
- <description><pre>".h($content)."</pre></description>
- </item>";
- $rss = str_replace('{WIKI_TITLE}', $WIKI_TITLE . ": " . $this->TP_COMMENTS, $this->rss_template);
- $rss = str_replace('{PAGE_LINK}', $pagelink, $rss);
- $rss = str_replace('{LANG}', $LANG, $rss);
- $rss = str_replace('{WIKI_DESCRIPTION}', "RSS comments feed from " . $WIKI_TITLE, $rss);
- $rss = str_replace('{CONTENT_RSS}', $n_item . $items, $rss);
- if(!$file = @fopen($this->rss_file, "w")) {
- echo "Opening file for writing RSS comments file is not possible! Please create file rss.xml in your var directory and make it writable (chmod 666).";
- return true;
- }
- fwrite($file, $rss);
- fclose($file);
- }
- /*
- * Need to move comments together with the page (during rename operation)
- */
- function pageWritten()
- {
- global $moveto, $PG_DIR;
- // page is already set to $moveto, we need to take original page name from the request
- $orig_name = $_REQUEST["page"];
- if(!$moveto || $moveto == $orig_name) // page was not moved, nothing to do
- return;
- if(file_exists($this->comments_dir . $orig_name))
- rename($this->comments_dir . $orig_name, $this->comments_dir . $moveto);
- }
- // Localization strings
- var $cs_strings = array(
- array("TP_FORM_NAME", "Jméno"),
- array("TP_FORM_EMAIL", "E-mail"),
- array("TP_FORM_CONTENT", "Obsah"),
- array("TP_FORM_SUBMIT", "Přidat"),
- array("TP_REPLY_TO", "Odpovědět na tento komentář"),
- array("TP_COMMENTS", "Komentáře"),
- array("TP_DELETE", "Smazat"),
- array("TP_DELETE_CONFIRM", "Chcete opravdu smazat tento komentář?"),
- );
- var $en_strings = array(
- array("TP_FORM_NAME", "Name"),
- array("TP_FORM_EMAIL", "E-mail"),
- array("TP_FORM_CONTENT", "Content"),
- array("TP_FORM_SUBMIT", "Save"),
- array("TP_REPLY_TO", "Reply to this comment"),
- array("TP_COMMENTS", "Comments"),
- array("TP_DELETE", "Delete"),
- array("TP_DELETE_CONFIRM", "Do you really want to delete this comment?")
- );
- var $fr_strings = array(
- array("TP_FORM_NAME", "Votre nom"),
- array("TP_FORM_EMAIL", "E-mail"),
- array("TP_FORM_CONTENT", "Votre commentaire"),
- array("TP_FORM_SUBMIT", "Envoyer"),
- array("TP_REPLY_TO", "Répondre à ce commentaire"),
- array("TP_COMMENTS", "Commentaires"),
- array("TP_DELETE", "Supprimer"),
- array("TP_DELETE_CONFIRM", "Voulez-vous supprimer ce commentaire ?")
- );
- function localize()
- {
- global $LANG;
- foreach($this->en_strings as $str)
- $this->$str[0] = $str[1];
- if($LANG != "en" && isset($this->{$LANG . "_strings"}))
- foreach($this->{$LANG . "_strings"} as $str)
- $this->$str[0] = $str[1];
- }
- }