PageRenderTime 62ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/assets/snippets/jot/jot.class.inc.php

https://github.com/modxcms/evolution
PHP | 910 lines | 883 code | 11 blank | 16 comment | 9 complexity | 0af2570c0642f53b775c8dac7fc853d0 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, MIT, BSD-2-Clause, Apache-2.0, BSD-3-Clause
  1. <?php
  2. /*####
  3. #
  4. # Name: Jot
  5. # Version: 1.1.4
  6. # Author: Armand "bS" Pondman (apondman@zerobarrier.nl)
  7. # Date: Aug 04, 2008
  8. #
  9. # Latest Version: http://modx.com/extras/package/jot
  10. # Jot Demo Site: http://projects.zerobarrier.nl/modx/
  11. # Documentation: http://wiki.modxcms.com/index.php/Jot (wiki)
  12. #
  13. ####*/
  14. class CJot {
  15. var $name;
  16. var $version;
  17. var $config = array();
  18. var $parameters = array();
  19. var $_ctime;
  20. var $_provider;
  21. var $_instance;
  22. var $templates = array();
  23. var $_link = array();
  24. function CJot() {
  25. global $modx;
  26. $path = strtr(realpath(dirname(__FILE__)), '\\', '/');
  27. include_once($path . '/includes/jot.db.class.inc.php');
  28. if (!class_exists('CChunkie'))
  29. include_once($path . '/includes/chunkie.class.inc.php');
  30. $this->name = $this->config["snippet"]["name"] = "Jot";
  31. $this->version = $this->config["snippet"]["version"] = "1.1.4"; //
  32. $this->config["snippet"]["versioncheck"] = "Unknown";
  33. $this->_ctime = time();
  34. $this->_check = 0;
  35. $this->provider = new CJotDataDb;
  36. $this->form = array();
  37. }
  38. function VersionCheck($version) {
  39. if ($version == $this->version) $this->_check = 1;
  40. $this->config["snippet"]["versioncheck"] = $version;
  41. }
  42. function Get($field) {
  43. return $this->parameters[$field];
  44. }
  45. function Set($field, $value) {
  46. $this->parameters[$field] = $value;
  47. }
  48. function UniqueId($docid = 0,$tagid = '') {
  49. // Creates a unique hash / id
  50. $id[] = $docid."&".$tagid."&";
  51. foreach ($this->parameters as $n => $v) { $id[] = $n.'='.($v); }
  52. return md5(implode('&',$id));
  53. }
  54. function Run() {
  55. global $modx;
  56. // Check version
  57. $this->config["path"] = $this->Get("path");
  58. if (!$this->_check) {
  59. $output = '<div style="border: 1px solid red;font-weight: bold;margin: 10px;padding: 5px;">
  60. Jot cannot load because the snippet code version ('.$this->config["snippet"]["versioncheck"].') isn\'t the same as the snippet included files version ('.$this->config["snippet"]["version"].').
  61. Possible cause is that you updated the jot files in the modx directory but didn\'t update the snippet code from the manager. The content for the updated snippet code can be found in jot.snippet.txt
  62. </div>';
  63. return $output;
  64. }
  65. // Add input parameters (just for debugging purposes)
  66. $this->config["snippet"]["input"] = $this->parameters;
  67. // General settings
  68. // TODO Add docid/tagid from all
  69. $this->config["docid"] = !is_null($this->Get("docid")) ? intval($this->Get("docid")):$modx->documentIdentifier;
  70. $this->config["tagid"] = !is_null($this->Get("tagid")) ? preg_replace("/[^A-z0-9_\-]/",'',$this->Get("tagid")):'';
  71. $this->config["pagination"] = !is_null($this->Get("pagination")) ? $this->Get("pagination") : 10; // Set pagination (0 = disabled, # = comments per page)
  72. $this->config["captcha"] = !is_null($this->Get("captcha")) ? intval($this->Get("captcha")) : 0; // Set captcha (0 = disabled, 1 = enabled, 2 = enabled for not logged in users)
  73. $this->config["postdelay"] = !is_null($this->Get("postdelay")) ? $this->Get("postdelay") : 15; // Set post delay in seconds
  74. $this->config["guestname"] = !is_null($this->Get("guestname")) ? $this->Get("guestname") : "Anonymous"; // Set guestname if none is specified
  75. $this->config["subscribe"] = !is_null($this->Get("subscribe")) ? intval($this->Get("subscribe")) : 0;
  76. $this->config["numdir"] = !is_null($this->Get("numdir")) ? intval($this->Get("numdir")) : 1;
  77. $this->config["placeholders"] = !is_null($this->Get("placeholders")) ? intval($this->Get("placeholders")) : 0;
  78. $this->config["authorid"] = !is_null($this->Get("authorid")) ? intval($this->Get("authorid")) : $modx->documentObject["createdby"];
  79. $this->config["title"] = !is_null($this->Get("title")) ? $this->Get("title") : $modx->documentObject["longtitle"];
  80. $this->config["subject"]["subscribe"] = !is_null($this->Get("subjectSubscribe")) ? $this->Get("subjectSubscribe") : "New reply to a topic you are watching";
  81. $this->config["subject"]["moderate"] = !is_null($this->Get("subjectModerate")) ? $this->Get("subjectModerate") : "New reply to a topic you are moderating";
  82. $this->config["subject"]["author"] = !is_null($this->Get("subjectAuthor")) ? $this->Get("subjectAuthor") : "New comment on your post";
  83. $this->config["debug"] = !is_null($this->Get("debug")) ? intval($this->Get("debug")) : 0;
  84. $this->config["output"] = !is_null($this->Get("output")) ? intval($this->Get("output")) : 1;
  85. $this->config["validate"] = !is_null($this->Get("validate")) ? $this->Get("validate") : "content:You forgot to enter a comment.";
  86. // CSS Settings (basic)
  87. $this->config["css"]["include"] = !is_null($this->Get("css")) ? intval($this->Get("css")) : 1;
  88. $this->config["css"]["file"] = !is_null($this->Get("cssFile")) ? $this->Get("cssFile") : "assets/snippets/jot/templates/jot.css";
  89. $this->config["css"]["rowalt"] = !is_null($this->Get("cssRowAlt")) ? $this->Get("cssAltRow") : "jot-row-alt";
  90. $this->config["css"]["rowme"] = !is_null($this->Get("cssRowMe")) ? $this->Get("cssRowMe") : "jot-row-me";
  91. $this->config["css"]["rowauthor"] = !is_null($this->Get("cssRowAuthor")) ? $this->Get("cssRowAuthor") : "jot-row-author";
  92. // Security
  93. $this->config["user"]["mgrid"] = intval($_SESSION['mgrInternalKey']);
  94. $this->config["user"]["usrid"] = intval($_SESSION['webInternalKey']);
  95. $this->config["user"]["id"] = ( $this->config["user"]["usrid"] > 0 ) ? (-$this->config["user"]["usrid"]) : $this->config["user"]["mgrid"];
  96. $this->config["user"]["host"] = $_SERVER['REMOTE_ADDR'];
  97. $this->config["user"]["ip"] = $_SERVER['REMOTE_ADDR'];
  98. $this->config["user"]["agent"] = $_SERVER['HTTP_USER_AGENT'];
  99. $this->config["user"]["sechash"] = md5($this->config["user"]["id"].$this->config["user"]["host"].$this->config["user"]["ip"].$this->config["user"]["agent"]);
  100. // Automatic settings
  101. $this->_instance = $this->config["id"] = $this->UniqueId($this->config["docid"],$this->config["tagid"]);
  102. $this->_idshort = substr($this->_instance,0,8);
  103. if($this->config["captcha"] == 2) { if ($this->config["user"]["id"]) { $this->config["captcha"] = 0;} else { $this->config["captcha"] = 1;} }
  104. $this->config["seed"] = rand();
  105. $this->config["doc.pagetitle"] = $modx->documentObject["pagetitle"];
  106. $this->config["customfields"] = $this->Get("customfields") ? explode(",",$this->Get("customfields")):array("name","email"); // Set names of custom fields
  107. $this->config["sortby"] = !is_null($this->Get("sortby")) ? $this->Get("sortby") : "createdon:d";
  108. $this->config["sortby"] = $this->validateSortString($this->config["sortby"]);
  109. // Set access groups
  110. $this->config["permissions"]["post"] = !is_null($this->Get("canpost")) ? explode(",",$this->Get("canpost")):array();
  111. $this->config["permissions"]["view"] = !is_null($this->Get("canview")) ? explode(",",$this->Get("canview")):array();
  112. $this->config["permissions"]["edit"] = !is_null($this->Get("canedit")) ? explode(",",$this->Get("canedit")):array();
  113. $this->config["permissions"]["moderate"] = !is_null($this->Get("canmoderate")) ? explode(",",$this->Get("canmoderate")):array();
  114. $this->config["permissions"]["trusted"] = !is_null($this->Get("trusted")) ? explode(",",$this->Get("trusted")):array();
  115. // Moderation
  116. $this->config["moderation"]["type"] = !is_null($this->Get("moderated")) ? intval($this->Get("moderated")) : 0;
  117. $this->config["moderation"]["notify"] = !is_null($this->Get("notify")) ? intval($this->Get("notify")) : 1;
  118. $this->config["moderation"]["notifyAuthor"] = !is_null($this->Get("notifyAuthor")) ? intval($this->Get("notifyAuthor")) : 0;
  119. // Access Booleans
  120. // TODO Add logic for manager groups
  121. $this->isModerator = $this->config["moderation"]["enabled"] = intval($modx->isMemberOfWebGroup($this->config["permissions"]["moderate"] ) || $modx->checkSession());
  122. $this->isTrusted = $this->config["moderation"]["trusted"] = intval($modx->isMemberOfWebGroup($this->config["permissions"]["trusted"] ) || $this->isModerator);
  123. $this->canPost = $this->config["user"]["canpost"] = ((count($this->config["permissions"]["post"])==0) || $modx->isMemberOfWebGroup($this->config["permissions"]["post"]) || $this->isModerator) ? 1 : 0;
  124. $this->canView = $this->config["user"]["canview"] = ((count($this->config["permissions"]["view"])==0) || $modx->isMemberOfWebGroup($this->config["permissions"]["view"]) || $this->isModerator) ? 1 : 0;
  125. $this->canEdit = $this->config["user"]["canedit"] = intval($modx->isMemberOfWebGroup($this->config["permissions"]["edit"]) || $this->isModerator);
  126. // Templates
  127. $this->templates["form"] = !is_null($this->Get("tplForm")) ? $this->Get("tplForm") : $this->config["path"]."/templates/chunk.form.inc.html";
  128. $this->templates["comments"] = !is_null($this->Get("tplComments")) ? $this->Get("tplComments") : $this->config["path"]."/templates/chunk.comment.inc.html";
  129. $this->templates["navigation"] = !is_null($this->Get("tplNav")) ? $this->Get("tplNav") : $this->config["path"]."/templates/chunk.navigation.inc.html";
  130. $this->templates["moderate"] = !is_null($this->Get("tplModerate")) ? $this->Get("tplModerate") : $this->config["path"]."/templates/chunk.moderate.inc.html";
  131. $this->templates["subscribe"] = !is_null($this->Get("tplSubscribe")) ? $this->Get("tplSubscribe") : $this->config["path"]."/templates/chunk.subscribe.inc.html";
  132. $this->templates["notify"] = !is_null($this->Get("tplNotify")) ? $this->Get("tplNotify") : $this->config["path"]."/templates/chunk.notify.inc.txt";
  133. $this->templates["notifymoderator"] = !is_null($this->Get("tplNotifyModerator")) ? $this->Get("tplNotifyModerator") : $this->config["path"]."/templates/chunk.notify.moderator.inc.txt";
  134. $this->templates["notifyauthor"] = !is_null($this->Get("tplNotifyAuthor")) ? $this->Get("tplNotifyAuthor") : $this->config["path"]."/templates/chunk.notify.author.inc.txt";
  135. // Querystring keys
  136. $this->config["querykey"]["action"] = "jot".$this->_idshort;
  137. $this->config["querykey"]["navigation"] = "jn".$this->_idshort;
  138. $this->config["querykey"]["id"] = "jid".$this->_idshort;
  139. $this->config["querykey"]["view"] = "jv".$this->_idshort;
  140. // Querystring values
  141. $this->config["query"]["action"] = $_GET[$this->config["querykey"]["action"]];
  142. $this->config["query"]["navigation"] = intval($_GET[$this->config["querykey"]["navigation"]]);
  143. $this->config["query"]["id"] = intval($_GET[$this->config["querykey"]["id"]]);
  144. $this->config["query"]["view"] = intval($_GET[$this->config["querykey"]["view"]]);
  145. // Form options
  146. $this->isPostback = $this->config["form"]["postback"] = ($_POST["JotForm"] == $this->_instance) ? 1 : 0;
  147. // Field validation array
  148. $valStrings = explode(",",$this->config["validate"]);
  149. $valFields = array();
  150. foreach($valStrings as $valString) {
  151. $valProp = explode(":",$valString,3);
  152. $valField = array();
  153. $valField["validation"] = "required";
  154. foreach($valProp as $i => $v) {
  155. if ($i==1) $valField["msg"] = $v;
  156. if ($i==2) $valField["validation"] = $v;
  157. }
  158. $valFields[$valProp[0]][] = $valField;
  159. }
  160. $this->config["form"]["validation"] = $valFields;
  161. //-- Initialize form array()
  162. $this->form = array();
  163. $this->form["source"] = $this->config["query"]["id"];
  164. $this->form["guest"] = ($this->config["user"]["id"]) ? 0 : 1;
  165. $this->form["field"] = array("custom" => array());
  166. $this->form["error"] = 0;
  167. $this->form["confirm"] = 0;
  168. $this->form["published"] = 0;
  169. $this->form["badwords"] = 0;
  170. $this->form["edit"] = 0;
  171. $this->form["save"] = 0;
  172. // Modes
  173. $this->config["mode"]["type"] = "comments";
  174. $this->config["mode"]["active"] = $this->config["query"]["action"];
  175. $this->config["mode"]["passive"] = $this->Get("action");
  176. // Generated links
  177. $this->_link = array($this->config["querykey"]["action"]=>NULL,$this->config["querykey"]["id"]=>NULL);
  178. $this->config["link"]["id"] = $this->_idshort;
  179. $this->config["link"]["current"] = $this->preserveUrl($modx->documentIdentifier,'',$this->_link);
  180. $this->config["link"]["navigation"] = $this->preserveUrl($modx->documentIdentifier,'',array_merge($this->_link,array($this->config["querykey"]["navigation"]=>NULL)),true);
  181. $this->config["link"]["subscribe"] = $this->preserveUrl($modx->documentIdentifier,'',array_merge($this->_link,array($this->config["querykey"]["action"]=>'subscribe')));
  182. $this->config["link"]["unsubscribe"] = $this->preserveUrl($modx->documentIdentifier,'',array_merge($this->_link,array($this->config["querykey"]["action"]=>'unsubscribe')));
  183. $this->config["link"]["save"] = $this->preserveUrl($modx->documentIdentifier,'',array_merge($this->_link,array($this->config["querykey"]["action"]=>'save',$this->config["querykey"]["id"]=>$this->config["query"]["id"])));
  184. $this->config["link"]["edit"] = $this->preserveUrl($modx->documentIdentifier,'',array_merge($this->_link,array($this->config["querykey"]["action"]=>'edit')),true);
  185. $this->config["link"]["delete"] = $this->preserveUrl($modx->documentIdentifier,'',array_merge($this->_link,array($this->config["querykey"]["action"]=>'delete')),true);
  186. $this->config["link"]["view"] = $this->preserveUrl($modx->documentIdentifier,'',array_merge($this->_link,array($this->config["querykey"]["view"]=>NULL)),true);
  187. $this->config["link"]["publish"] = $this->preserveUrl($modx->documentIdentifier,'',array_merge($this->_link,array($this->config["querykey"]["action"]=>'publish')),true);
  188. $this->config["link"]["unpublish"] = $this->preserveUrl($modx->documentIdentifier,'',array_merge($this->_link,array($this->config["querykey"]["action"]=>'unpublish')),true);
  189. // Check for first run
  190. $this->provider->FirstRun($this->config["path"]);
  191. // Badwords
  192. $this->config["badwords"]["enabled"] = !is_null($this->Get("badwords")) ? 1 : 0;
  193. $this->config["badwords"]["type"] = !is_null($this->Get("bw")) ? intval($this->Get("bw")) : 1;
  194. if($this->config["badwords"]["enabled"]) {
  195. $badwords = $this->Get("badwords");
  196. $badwords = preg_replace("~([\n\r\t\s]+)~","",$badwords);
  197. $this->config["badwords"]["words"] = explode(",",$badwords);
  198. $this->config["badwords"]["regexp"] = "~" . implode("|",$this->config["badwords"]["words"]) . "~i";
  199. }
  200. // Moderation
  201. if ($this->isModerator) {
  202. $this->config["moderation"]["view"] = $view = isset($_GET[$this->config["querykey"]["view"]]) ? $this->config["query"]["view"]: 2;
  203. }
  204. // Subscription
  205. $this->config["subscription"]["enabled"] = 0;
  206. $this->config["subscription"]["status"] = 0;
  207. if ($this->config["user"]["id"] && $this->config["subscribe"]) {
  208. $this->config["subscription"]["enabled"] = 1;
  209. $isSubscribed = $this->provider->hasSubscription($this->config["docid"],$this->config["tagid"], $this->config["user"]);
  210. if ($isSubscribed) $this->config["subscription"]["status"] = 1;
  211. }
  212. $commentId = $this->config["query"]["id"];
  213. // Active action
  214. switch ($this->config["mode"]["active"]) {
  215. case "delete":
  216. $this->doModerate('delete',$commentId);
  217. break;
  218. case "publish":
  219. $this->doModerate('publish',$commentId);
  220. break;
  221. case "unpublish":
  222. $this->doModerate('unpublish',$commentId);
  223. break;
  224. case "edit":
  225. if ($this->isModerator) {
  226. $this->doModerate('edit',$commentId);
  227. break;
  228. } else {
  229. $this->form["edit"] = 1;
  230. }
  231. case "save":
  232. if ($this->isModerator) {
  233. $this->doModerate('save',$commentId);
  234. break;
  235. } else {
  236. $this->form["edit"] = 1;
  237. $this->form["save"] = 1;
  238. }
  239. case "move":
  240. break;
  241. case "subscribe":
  242. if ($this->config["subscription"]["enabled"] == 1) {
  243. if ($this->config["subscription"]["status"] == 0) {
  244. $this->provider->Subscribe($this->config["docid"],$this->config["tagid"],$this->config["user"]);
  245. $this->config["subscription"]["status"] = 1;
  246. }
  247. }
  248. break;
  249. case "unsubscribe":
  250. if ($this->config["subscription"]["enabled"] == 1) {
  251. if ($this->config["subscription"]["status"] == 1) {
  252. $this->provider->Unsubscribe($this->config["docid"],$this->config["tagid"],$this->config["user"]);
  253. $this->config["subscription"]["status"] = 0;
  254. }
  255. }
  256. break;
  257. }
  258. // Form Processing
  259. $frmCommentId = ($this->form["edit"]) ? $commentId : 0;
  260. $this->processForm($frmCommentId);
  261. // Passive Action
  262. switch ($this->config["mode"]["passive"]) {
  263. case "count-comments" : $output = $this->getCommentCount(); break;
  264. case "count-subscriptions": $output = $this->SubscriptionCount(); break;
  265. case "comments": $output = $this->getOutputComments(); break;
  266. case "form": $output = $this->getOutputForm(); break;
  267. case "blank": break;
  268. case "default":
  269. default: $output = $this->getOutputDefault(); break;
  270. }
  271. if ($this->config["debug"]) {
  272. $output .= '<br /><hr /><b>'.$this->name.' '.$this->version.': Debug</b><hr /><pre style="overflow: auto;background-color: white;font-weight: bold;">';
  273. $output .= $this->getOutputDebug($this->config,"jot");
  274. $output .= '</pre><hr />';
  275. }
  276. // Dump config into placeholders?
  277. if ($this->config["placeholders"]) $this->setPlaceholders($this->config,"jot");
  278. // Include stylesheet if needed
  279. $src = '<link rel="stylesheet" type="text/css" href="'.$modx->config["site_url"].$this->config["css"]["file"].'" />';
  280. if ($this->config["css"]["include"]) $modx->regClientCSS($src);
  281. return $output;
  282. }
  283. // Output snippet values in debug format
  284. function getOutputDebug($value = '', $key = '', $path = '') {
  285. $keypath = !empty($path) ? $path . "." . $key : $key;
  286. $output = array();
  287. if (is_array($value)) {
  288. foreach ($value as $subkey => $subval) {
  289. $output[] = $this->getOutputDebug($subval, $subkey, $keypath);
  290. }
  291. } else {
  292. $output[] = '<span style="color: navy;">'.$keypath.'</span> = <span style="color: maroon;">'.htmlspecialchars($value).'</span><br />';
  293. }
  294. return implode("",$output);
  295. }
  296. // Create placeholders in MODX from arrays
  297. function setPlaceholders($value = '', $key = '', $path = '') {
  298. global $modx;
  299. $keypath = !empty($path) ? $path . "." . $key : $key;
  300. $output = array();
  301. if (is_array($value)) {
  302. foreach ($value as $subkey => $subval) {
  303. $this->setPlaceholders($subval, $subkey, $keypath);
  304. }
  305. } else {
  306. if (strlen($this->config["tagid"]) > 0) {$keypath .= ".".$this->config["tagid"]; }
  307. $modx->setPlaceholder($keypath,$value);
  308. }
  309. }
  310. // Display default
  311. function getOutputDefault() {
  312. global $modx;
  313. $output = $this->getOutputForm();
  314. $output .= $this->getOutputComments();
  315. return $output;
  316. }
  317. // Display comments
  318. function getOutputComments() {
  319. // Check if viewing is allowed
  320. if($this->canView) {
  321. // View (Moderation)
  322. $view = 1;
  323. if ($this->isModerator) {
  324. $view = $this->config["moderation"]["view"];
  325. $this->config["moderation"]["unpublished"] = $this->getCommentCount(0);
  326. $this->config["moderation"]["published"] = $this->getCommentCount(1);
  327. $this->config["moderation"]["mixed"] = $this->getCommentCount(2);
  328. }
  329. // Get total number of comments
  330. $commentTotal = $this->getCommentCount($view);
  331. $pagination = $this->config["pagination"];
  332. // Apply pagination if enabled
  333. if ($pagination > 0) {
  334. $pageLength = $pagination;
  335. $pageTotal = ceil($commentTotal / $pageLength);
  336. $pageCurrent = isset($_GET[$this->config["querykey"]["navigation"]]) ? intval($_GET[$this->config["querykey"]["navigation"]]): 1;
  337. if ( ($pageCurrent < 1) || ($pageCurrent > $pageTotal) ) { $pageCurrent = 1; };
  338. $pageOffset = (($pageCurrent*$pageLength)-$pageLength);
  339. $navStart = ($pageOffset+1);
  340. $navEnd = ($pageOffset+$pageLength) > $commentTotal ? $commentTotal : ($pageOffset+$pageLength);
  341. } else {
  342. $pageLength = 0;
  343. $pageOffset = 0;
  344. $pageTotal = 1;
  345. $pageCurrent = 1;
  346. $navStart = 0;
  347. $navEnd = $commentTotal;
  348. }
  349. // Navigation
  350. $this->config['nav'] = array('total'=>$commentTotal,'start'=>$navStart,'end'=> $navEnd);
  351. $this->config['page'] = array('length'=>$pageLength,'total'=>$pageTotal,'current'=>$pageCurrent);
  352. // Render Moderation Options
  353. $output_moderate = NULL;
  354. if ($this->isModerator) {
  355. $tpl = new CChunkie($this->templates["moderate"]);
  356. $tpl->AddVar('jot',$this->config);
  357. $this->config["html"]["moderate"] = $output_moderate = $tpl->Render();
  358. }
  359. // Get comments
  360. $array_comments = $this->provider->GetComments($this->config["docid"],$this->config["tagid"],$view,$this->config["sortby"],$pageOffset,$pageLength);
  361. // Render navigation
  362. $output_navigation = NULL;
  363. if (($pagination > 0) && ($pageTotal > 1) ) {
  364. $tpl = new CChunkie($this->templates["navigation"]);
  365. $tpl->AddVar('jot',$this->config);
  366. $output_navigation = $tpl->Render();
  367. }
  368. // Render subscription options
  369. $output_subscribe = NULL;
  370. $tpl = new CChunkie($this->templates["subscribe"]);
  371. $tpl->AddVar('jot',$this->config);
  372. $this->config["html"]["subscribe"] = $output_subscribe = $tpl->Render();
  373. // Render comments
  374. $count = count($array_comments);
  375. $comments = array();
  376. // Comment Numbering
  377. for ($i = 0; $i < $count; $i++) {
  378. $num = ($this->config["numdir"]) ? $commentTotal - ($pageOffset + $i) : $pageOffset + ($i+1);
  379. $array_comments[$i]["postnumber"] = $num;
  380. }
  381. for ($i = 0; $i < $count; $i++) {
  382. $chunk["rowclass"] = $this->getChunkRowClass($i+1,$array_comments[$i]["createdby"]);
  383. $tpl = new CChunkie($this->templates["comments"]);
  384. $tpl->AddVar('jot',$this->config);
  385. $tpl->AddVar('comment',$array_comments[$i]);
  386. $tpl->AddVar('chunk',$chunk);
  387. $comments[] = $tpl->Render();
  388. }
  389. $this->config["html"]["comments"] = $output_comments = implode("",$comments);
  390. $this->config["html"]["navigation"] = $output_navigation;
  391. $output_comments = $output_subscribe.$output_moderate.$output_navigation.$output_comments.$output_navigation;
  392. }
  393. if ($this->config["output"]) return $output_comments;
  394. }
  395. function processForm($id=0) {
  396. global $modx;
  397. // Comment
  398. $id = intval($id);
  399. $pObj = $this->provider;
  400. $formMode = $this->config["mode"]["passive"];
  401. $saveComment = 1;
  402. $this->form["action"] = $this->config["link"]["current"];
  403. if ($id && $pObj->isValidComment($this->config["docid"],$this->config["tagid"],$id) && $this->canEdit) {
  404. $pObj->Comment($id);
  405. if (($pObj->Get("createdby") == $this->config["user"]["id"]) || $this->isModerator) {
  406. $this->form["action"] = $this->config["link"]["save"];
  407. $this->form['guest'] = ($pObj->Get("createdby") == 0) ? 1 : 0;
  408. $this->form["field"] = $pObj->getFields();
  409. $this->config["mode"]["passive"] = "form";
  410. } else {
  411. $this->form['edit'] = 0;
  412. $this->form['save'] = 0;
  413. $saveComment = 0;
  414. }
  415. } else {
  416. $pObj->Comment(0); // fix for update/new problem
  417. }
  418. // If this is not a postback or a false edit then return.
  419. if (!$this->isPostback || !$saveComment) return;
  420. // If we get here switch passive mode back and let the save option decide the final passive mode
  421. $this->config["mode"]["passive"] = $formMode;
  422. //-- Get Post Objects
  423. $chkPost = array();
  424. $valFields = array();
  425. // For every field posted loop
  426. foreach($_POST as $n=>$v) {
  427. // Stripslashes if needed
  428. if (get_magic_quotes_gpc()) { $v = stripslashes($v); }
  429. // Avoid XSS
  430. $v = $modx->htmlspecialchars($v, ENT_QUOTES);
  431. // Validate fields and store error level + msg in array
  432. $valFields[] = $this->validateFormField($n,$v);
  433. // Store field data
  434. switch($n) {
  435. case 'title': // Title field
  436. if ($v == '') $v = "Re: " . $this->config["title"];
  437. $this->form["field"]["title"] = $v;
  438. $pObj->Set("title",$v);
  439. break;
  440. case 'content': // Content field
  441. $this->form["field"]["content"] = $v;
  442. $pObj->Set("content",$v);
  443. break;
  444. default: // Custom fields
  445. if (in_array($n, $this->config["customfields"])) {
  446. $this->form["field"]["custom"][$n] = $v;
  447. $pObj->SetCustom($n,$v);
  448. } else {
  449. $this->form["field"][$n] = $v;
  450. }
  451. }
  452. //-- Detect bad words
  453. if ($this->config["badwords"]["enabled"]) $this->form['badwords'] = $this->form['badwords'] + preg_match_all($this->config["badwords"]["regexp"],$v,$matches);
  454. //--
  455. $chkPost[] = $n.'='.($v);
  456. } // --
  457. //-- Double Post Capture
  458. $chkPost = md5(implode('&',$chkPost));
  459. if ($_SESSION['JotLastPost'] == $chkPost) {
  460. $this->form['error'] = 1;
  461. $this->form['confirm'] = 0;
  462. $saveComment = 0;
  463. } else {
  464. $_SESSION['JotLastPost'] = $chkPost;
  465. }
  466. //-- Security check (Post Delay?)
  467. if ($saveComment && $this->form['error'] == 0 && $this->config["postdelay"] != 0 && $pObj->hasPosted($this->config["postdelay"],$this->config["user"])) {
  468. $this->form['error'] = 3; // Post to fast (within delay)
  469. return;
  470. };
  471. //-- Captcha/Veriword
  472. if ($saveComment && !(($this->config["captcha"] == 0 || isset($_POST['vericode']) && isset($_SESSION['veriword']) && $_SESSION['veriword'] == $_POST['vericode']))) {
  473. $this->form['error'] = 2; // Veriword / Captcha incorrect
  474. unset($pObj);
  475. return;
  476. } else {
  477. $_SESSION['veriword'] = md5($this->config["seed"]);
  478. }
  479. //-- Validate fields
  480. if ($saveComment) {
  481. foreach($valFields as $valid) {
  482. if (!$valid[0]) {
  483. $this->form['error'] = 5;
  484. $this->form['errormsg'] = $valid[1];
  485. $this->form['confirm'] = 0;
  486. $saveComment = 0;
  487. return;
  488. }
  489. }
  490. }
  491. // Everything OK so far
  492. if ($saveComment) {
  493. $this->form['confirm'] = 1;
  494. $this->form['published'] = 1;
  495. }
  496. //-- Check publish settings (moderations)
  497. if ($saveComment && $this->config["moderation"]["type"] && !$this->isTrusted) {
  498. $this->form['confirm'] = 2;
  499. $this->form['published'] = 0;
  500. }
  501. // Badwords detection logic
  502. if ($saveComment && $this->form["badwords"] && $this->config["badwords"]["enabled"] && !$this->isTrusted) {
  503. switch($this->config["badwords"]["type"]) {
  504. case 2: // Post Rejected
  505. $this->form['error'] = 4;
  506. $this->form['confirm'] = 0;
  507. $saveComment = 0;
  508. break;
  509. case 1: // Post Not Published
  510. $this->form['published'] = 0;
  511. $this->form['confirm'] = 2; // Post Not Published
  512. break;
  513. }
  514. }
  515. // If published or unpublished save the comment, else do nothing.
  516. if (!$id) {
  517. // this is a new post
  518. $pObj->Set("createdon",$this->_ctime);
  519. $pObj->Set("createdby",$this->config["user"]["id"]);
  520. $pObj->Set("secip",$this->config["user"]["ip"]);
  521. $pObj->Set("sechash",$this->config["user"]["sechash"]);
  522. $pObj->Set("uparent",$this->config["docid"]);
  523. $pObj->Set("tagid",$this->config["tagid"]);
  524. } else {
  525. // edit/save
  526. $pObj->Set("editedon",$this->_ctime);
  527. $pObj->Set("editedby",$this->config["user"]["id"]);
  528. }
  529. $pObj->Set("published",$this->form['published']);
  530. if ($saveComment) $pObj->Save();
  531. // Edit mode logic
  532. if ($saveComment && $this->form["save"]) {
  533. $this->form["moderation"] = 0;
  534. $this->form["edit"] = 0;
  535. if($this->form["confirm"]==1) $this->form["confirm"] = 3;
  536. $this->form["action"] = $this->config["link"]["current"];
  537. }
  538. if ($this->form["edit"]) { $this->config["mode"]["passive"] = "form"; }
  539. // Notify Subscribers
  540. if ($saveComment && $this->form['published']>0) $this->doNotifySubscribers($pObj->Get("id"));
  541. // Notify Moderators
  542. if ($saveComment && (($this->form['published']==0) || ($this->form['published'] >0 && $this->config["moderation"]["notify"]==2))) $this->doNotifyModerators($pObj->Get("id"));
  543. // Notify Author
  544. if ($saveComment && $this->config["moderation"]["notifyAuthor"]) $this->doNotifyAuthor($pObj->Get("id"));
  545. // If no error occured clear fields.
  546. if ($this->form['error'] <= 0 ) $this->form["field"] = array();
  547. // Destroy Comment Object and return form array()
  548. unset($pObj);
  549. return;
  550. }
  551. // Display Form
  552. function getOutputForm() {
  553. global $modx;
  554. $output_form = NULL;
  555. //---- Allow post?
  556. if ($this->canPost) {
  557. // Render Form
  558. $tpl = new CChunkie($this->templates["form"]);
  559. $tpl->AddVar('jot',$this->config);
  560. $tpl->AddVar('form',$this->form);
  561. $this->config["html"]["form"] = $output_form = $tpl->Render();
  562. } // -----
  563. // Output or placeholder?
  564. if ($this->config["output"]) return $output_form;
  565. }
  566. // Notifications
  567. function doNotifySubscribers($commentid=0) {
  568. global $modx;
  569. if ($this->config["subscription"]["enabled"]) {
  570. // Get comment fields
  571. $cObj = $this->provider;
  572. $cObj->Comment($commentid);
  573. $comment = $cObj->getFields();
  574. unset($cObj);
  575. $subscriptions = $this->provider->getSubscriptions($this->config["docid"],$this->config["tagid"]);
  576. $count = count($subscriptions);
  577. for ($i = 0; $i < $count; $i++) {
  578. if ($this->config["user"]["id"] != $subscriptions[$i]["userid"] ) {
  579. $user = $this->getUserInfo($subscriptions[$i]["userid"]);
  580. $tpl = new CChunkie($this->templates["notify"]);
  581. $tpl->AddVar('jot',$this->config);
  582. $tpl->AddVar('comment',$comment);
  583. $tpl->AddVar('siteurl',"http://".$_SERVER["SERVER_NAME"]);
  584. $tpl->AddVar('recipient',$user);
  585. $message = $tpl->Render();
  586. mail($user["email"], $this->config["subject"]["subscribe"], $message, "From: ".$modx->config['emailsender']."\r\n"."X-Mailer: Content Manager - PHP/".phpversion());
  587. }
  588. }
  589. }
  590. }
  591. // Moderator Notification
  592. function doNotifyModerators($commentid=0) {
  593. global $modx;
  594. if ($this->config["moderation"]["notify"]) {
  595. // Get comment fields
  596. $cObj = $this->provider;
  597. $cObj->Comment($commentid);
  598. $comment = $cObj->getFields();
  599. unset($cObj);
  600. $moderators = $this->getMembersOfWebGroup($this->config["permissions"]["moderate"]);
  601. foreach ($moderators as $moderator){
  602. $user = $modx->getWebUserInfo($moderator);
  603. $tpl = new CChunkie($this->templates["notifymoderator"]);
  604. $tpl->AddVar('jot',$this->config);
  605. $tpl->AddVar('comment',$comment);
  606. $tpl->AddVar('siteurl',"http://".$_SERVER["SERVER_NAME"]);
  607. $tpl->AddVar('recipient',$user);
  608. $message = $tpl->Render();
  609. mail($user["email"], $this->config["subject"]["moderate"], $message, "From: ".$modx->config['emailsender']."\r\n"."X-Mailer: Content Manager - PHP/".phpversion());
  610. }
  611. }
  612. }
  613. // Author Notification
  614. function doNotifyAuthor($commentid=0) {
  615. echo '<!-- notifying author -->';
  616. global $modx;
  617. if ($this->config["moderation"]["notifyAuthor"]) {
  618. // What is the e-mail address of the article author?
  619. $author_id = $this->config['authorid'];
  620. $res = $modx->db->select('*', $modx->getFullTableName('user_attributes'), "id = '{$author_id}'");
  621. $results_array = $modx->db->makeArray($res);
  622. $user = $results_array[0]; // Assume there is only one result
  623. // Get comment fields (copied from doNotifyModerators)
  624. $cObj = $this->provider;
  625. $cObj->Comment($commentid);
  626. $comment = $cObj->getFields();
  627. unset($cObj);
  628. $tpl = new CChunkie($this->templates["notifyauthor"]);
  629. $tpl->AddVar('jot',$this->config);
  630. $tpl->AddVar('comment',$comment);
  631. $tpl->AddVar('siteurl',"http://".$_SERVER["SERVER_NAME"]);
  632. $tpl->AddVar('recipient',$user);
  633. $message = $tpl->Render();
  634. mail($user["email"], $this->config["subject"]["author"], $message, "From: ".$modx->config['emailsender']."\r\n"."X-Mailer: Content Manager - PHP/".phpversion());
  635. }
  636. }
  637. // Returns comment count
  638. function getCommentCount($view=1) {
  639. return $this->provider->GetCommentCount($this->config["docid"],$this->config["tagid"],$view);
  640. }
  641. // Moderation
  642. function doModerate($action = '',$id = 0) {
  643. $output = NULL;
  644. $pObj = $this->provider;
  645. if ($this->isModerator && $pObj->isValidComment($this->config["docid"],$this->config["tagid"],$id)) {
  646. switch ($action) {
  647. case "delete":
  648. $pObj->Comment($id);
  649. $pObj->Delete();
  650. break;
  651. case "publish":
  652. $pObj->Comment($id);
  653. $pObj->Set("publishedon",$this->_ctime);
  654. $pObj->Set("publishedby",$this->config["user"]["id"]);
  655. $pObj->Set("published",1);
  656. $pObj->Save();
  657. $this->doNotifySubscribers($id);
  658. break;
  659. case "edit":
  660. $this->form["moderation"] = 1;
  661. $this->form["edit"] = 1;
  662. break;
  663. case "save":
  664. $this->form["moderation"] = 1;
  665. $this->form["edit"] = 1;
  666. $this->form["save"] = 1;
  667. break;
  668. case "unpublish":
  669. $pObj->Comment($id);
  670. $pObj->Set("publishedon",$this->_ctime);
  671. $pObj->Set("publishedby",$this->config["user"]["id"]);
  672. $pObj->Set("published",0);
  673. $pObj->Save();
  674. break;
  675. }
  676. }
  677. unset($pObj);
  678. return $output;
  679. }
  680. // Templating
  681. function getChunkRowClass($count,$userid) {
  682. $rowstyle = ($count%2) ? "jot-row-alt" : "";
  683. if ( $this->config["user"]["id"] == $userid && ($userid != 0)) {
  684. $rowstyle .= " jot-row-me";
  685. } elseif ( $this->config["authorid"] == $userid && ($userid != 0) ) {
  686. $rowstyle .= " jot-row-author";
  687. }
  688. return $rowstyle;
  689. }
  690. // Validate a field
  691. function validateFormField($name = '', $value = '') {
  692. $returnValue = array(1,"");
  693. $validateFields = $this->config["form"]["validation"];
  694. // Validation Exists?
  695. if (!array_key_exists($name, $validateFields))
  696. return $returnValue;
  697. // Load field validation array
  698. $validations = $validateFields[$name];
  699. // Loop validation array
  700. foreach($validations as $validation) {
  701. switch ($validation["validation"]) {
  702. // email validation
  703. case "email": $re = "~^(?:[a-z0-9_-]+?\.)*?[a-z0-9_-]+?@(?:[a-z0-9_-]+?\.)*?[a-z0-9_-]+?\.[a-z0-9]{2,5}$~i"; break;
  704. // simple required field validation
  705. case "required": $re = "~.+~s";break;
  706. // simple number validation
  707. case "number": $re = "~^\d+$~";break;
  708. // custom regexp pattern
  709. default: $re = $validation["validation"]; break;
  710. }
  711. // if not a match return error msg
  712. if (!preg_match($re,$value))
  713. return array(0,$validation["msg"]);
  714. }
  715. return $returnValue;
  716. }
  717. // Validates and returns a special sort string so the data provider can handle this.
  718. function validateSortString($strSort = '') {
  719. $z = array();
  720. $xObj = $this->provider;
  721. $xObj->Comment();
  722. $y = explode(",",$strSort); // suggested sort fields
  723. $x = $xObj->getFields(); // actual available sort fields
  724. $x2 = $this->config["customfields"]; // actual available custom sort fields
  725. unset($xObj);
  726. // for each suggested sort
  727. foreach ($y as $i) {
  728. $i = trim($i);
  729. if(strlen($i)>2) {
  730. // get direction
  731. $dir = substr($i, -2);
  732. // get fieldname
  733. $name = substr($i,0,(strlen($i)-2));
  734. // if this is a custom field prefix with '#' so data provider can detect it.
  735. if (in_array($name, $x2)) { $z[] = "#".$name.$dir; }
  736. // if normal field
  737. elseif (array_key_exists($name, $x)) { $z[] = $name.$dir; }
  738. }
  739. }
  740. return implode(",",$z);
  741. }
  742. // Returns an array containing webusers which are a member of the specified group(s).
  743. function getMembersOfWebGroup($groupNames=array()) {
  744. global $modx;
  745. $rs = $modx->db->select(
  746. 'DISTINCT wg.webuser',
  747. $modx->getFullTableName("webgroup_names")." wgn
  748. INNER JOIN ".$modx->getFullTableName("web_groups")." wg ON wg.webgroup=wgn.id AND wgn.name IN ('" . implode("','",$groupNames) . "')"
  749. );
  750. $usrIDs = $modx->db->getColumn("webuser", $rs);
  751. $usrIDs = array_filter(array_map('intval', $usrIDs));
  752. return $usrIDs;
  753. }
  754. // MODX UserInfo enhanced
  755. function getUserInfo($userid = 0,$field = NULL) {
  756. global $modx;
  757. if (intval($userid) < 0) {
  758. $user = $modx->getWebUserInfo(-($userid));
  759. } else {
  760. $user = $modx->getUserInfo($userid);
  761. }
  762. if ($field) { return $user[$field]; }
  763. return $user;
  764. }
  765. // MODX makeUrl enhanced: preserves querystring.
  766. function preserveUrl($docid = '', $alias = '', $array_values = array(), $suffix = false) {
  767. global $modx;
  768. $array_get = $_GET;
  769. $urlstring = array();
  770. unset($array_get["id"]);
  771. unset($array_get["q"]);
  772. $array_url = array_merge($array_get, $array_values);
  773. foreach ($array_url as $name => $value) {
  774. if (!is_null($value)) {
  775. $urlstring[] = $name . '=' . urlencode($modx->htmlspecialchars($value, ENT_QUOTES));
  776. }
  777. }
  778. $url = implode('&',$urlstring);
  779. if ($suffix) {
  780. if (empty($url)) { $url = "?"; }
  781. else { $url .= "&"; }
  782. }
  783. return $modx->makeUrl($docid, $alias, $url);
  784. }
  785. }
  786. ?>