PageRenderTime 24ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

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

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