PageRenderTime 67ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/mem_moderation/mem_moderation_article.php

https://bitbucket.org/Manfre/txp-plugins
PHP | 1625 lines | 1319 code | 220 blank | 86 comment | 144 complexity | 91746002f2a7f5cb31ad54c21d289c80 MD5 | raw file
  1. <?php
  2. // Copy this file to a new name like abc_myplugin.php. Edit the code, then
  3. // run this file at the command line to produce a plugin for distribution:
  4. // $ php abc_myplugin.php > abc_myplugin-0.1.txt
  5. // Plugin name is optional. If unset, it will be extracted from the current
  6. // file name. Uncomment and edit this line to override:
  7. $plugin['name'] = 'mem_moderation_article';
  8. $plugin['version'] = '0.7.6';
  9. $plugin['author'] = 'Michael Manfre';
  10. $plugin['author_uri'] = 'http://manfre.net/';
  11. $plugin['description'] = 'Moderation plugin that allows articles to be submitted to the moderation queue.';
  12. $plugin['type'] = 1; // 0 for regular plugin; 1 if it includes admin-side code
  13. @include_once('../zem_tpl.php');
  14. if (0) {
  15. ?>
  16. # --- BEGIN PLUGIN HELP ---
  17. h1(title). mem_moderation_article plugin
  18. h2(section summary). Summary
  19. p. This moderation plugin allows users to submit articles in to the moderation queue.
  20. h2(section contact). Author Contact
  21. "Michael Manfre":mailto:mmanfre@gmail.com?subject=Textpattern%20mem_moderation_article%20plugin
  22. "http://manfre.net":http://manfre.net
  23. h2(section license). License
  24. p. This plugin is licensed under the "GPLv2":http://www.fsf.org/licensing/licenses/info/GPLv2.html.
  25. h2(section installation). Installation
  26. p. "Start Install Wizard":./index.php?event=article_moderate&step=preinstall
  27. h2(section tags). Tags
  28. * "mem_if_owns_article":#mem_if_owns_article
  29. * "mem_article_action_link":#mem_article_action_link
  30. * "mem_article_delete_sentry":#mem_article_delete_sentry
  31. * "mem_custom_user_article_list":#mem_custom_user_article_list
  32. * "mem_moderation_article_form":#mem_moderation_article_form
  33. * "mem_gps_category":#mem_gps_category
  34. * "mem_gps_section":#mem_gps_section
  35. * "mod_article_form":#mod_article_form _(deprecated)_
  36. * "mod_custom_input":#mod_custom_input _(deprecated)_
  37. * "mod_title_input":#mod_title_input _(deprecated)_
  38. * "mod_image_input":#mod_image_input _(deprecated)_
  39. * "mod_keywords_input":#mod_keywords_input _(deprecated)_
  40. * "mod_body_input":#mod_body_input _(deprecated)_
  41. * "mod_body_html_input":#mod_body_html_input _(deprecated)_
  42. * "mod_excerpt_input":#mod_excerpt_input _(deprecated)_
  43. * "mod_excerpt_html_input":#mod_excerpt_html_input _(deprecated)_
  44. h3(tag#mem_if_owns_article). mem_if_owns_article
  45. p(tag-summary). Conditionally parse enclosed text based upon if the current user is the creater of the displayed article.
  46. *(atts) %(atts-name)useridfield% %(atts-type)string% Name of the table field holding the user id. Default is "AuthorID".
  47. h3(tag#mem_article_action_link). mem_article_action_link
  48. p(tag-summary). Output a url (or link) for the current article that can be used by the delete sentry. Works with any tag supporting $thisarticle.
  49. *(atts) %(atts-name)action% %(atts-type)string% Action that is encoded in to the url. Default is delete.
  50. * %(atts-name)text% %(atts-type)string% Link text value.
  51. * %(atts-name)url% %(atts-type)string% URL to sentry or other handler, relative to site root.
  52. * %(atts-name)mode% %(atts-type)string% Mode for generating output. url_only = raw URL, url_encoded = encoded URL, url_escaped = html escaped URL, link = HTML a tag. Default is link.
  53. * %(atts-name)prompt% %(atts-type)string% Javascript prompt text.
  54. h3(tag#mem_article_delete_sentry). mem_article_delete_sentry
  55. p(tag-summary). Listens for and validates delete links and adds moderation item to queue.
  56. *(atts) %(atts-name)successmsg% %(atts-type)string% Message to show on success.
  57. * %(atts-name)failuremsg% %(atts-type)string% Message to show on failure.
  58. * %(atts-name)wraptag% %(atts-type)string% HTML tag to wrap message.
  59. * %(atts-name)class% %(atts-type)string% CSS class for wraptag.
  60. h3(tag#mem_custom_user_article_list). mem_custom_user_article_list
  61. p(tag-summary). Article list (same as article_custom), except has the ability to filters based upon a user id being stored in another database field.
  62. *(atts) %(atts-name)useridfield% %(atts-type)string% DB Field that holds the user id.
  63. * %(atts-name)form% %(atts-type)string% Form containing article tags.
  64. * %(atts-name)limit% %(atts-type)int% Max number of articles in list.
  65. * %(atts-name)offset% %(atts-type)int% Number of articles to skip.
  66. * %(atts-name)pageby% %(atts-type)int% Number of articles per page.
  67. * %(atts-name)category% %(atts-type)string% Restricts articles to those that have category1 or category2 matching value.
  68. * %(atts-name)section% %(atts-type)string% Restricts to articles matching section.
  69. * %(atts-name)author% %(atts-type)string% Restricts to articles matching author.
  70. * %(atts-name)sort% %(atts-type)string% SQL sort field and direction.
  71. * %(atts-name)time% %(atts-type)string% Article timeframe. any = include all articles, future = Posted > now(), default = Posted < now()
  72. * %(atts-name)month% %(atts-type)string% Restrict to articles posted during the month of.
  73. * %(atts-name)status% %(atts-type)string% Restrict to articles matching status
  74. h3(tag#mem_moderation_article_form). mem_moderation_article_form
  75. p(tag-summary). mem_form helper tag for article edits. See mem_form for tag attributes and usage.
  76. h3(tag#mod_article_form). mod_article_form _(deprecated)_
  77. p(tag-summary). This client side tag will place a form for submitting and re-editing submitted articles.
  78. *(atts) %(atts-name)form% %(atts-type)string% The txp form that holds the layout tags.
  79. * %(atts-name)successform% %(atts-type)string% The txp form that holds the template to show to the user on a successful form submission (for either save, edit, or delete).
  80. h3(tag#mod_custom_input). mod_custom_input _(deprecated)_
  81. p(tag-summary). Display a text input field for custom input fields.
  82. *(atts) %(atts-name)class% %(atts-type)string% The CSS class name to associate with the outputted HTML tag
  83. * %(atts-name)isize% %(atts-type)int% The size of the input field.
  84. * %(atts-name)id% %(atts-type)int% The field id this tag represents. E.g. id="1" matches field custom_1
  85. h3(tag#mod_title_input). mod_title_input _(deprecated)_
  86. p(tag-summary). Display a text input field for the title.
  87. *(atts) %(atts-name)class% %(atts-type)string% The CSS class name to associate with the outputted HTML tag
  88. * %(atts-name)isize% %(atts-type)int% The size of the input field.
  89. h3(tag#mod_image_input). mod_image_input _(deprecated)_
  90. p(tag-summary). Display a text input field for the article image field.
  91. *(atts) %(atts-name)class% %(atts-type)string% The CSS class name to associate with the outputted HTML tag
  92. * %(atts-name)isize% %(atts-type)int% The size of the input field.
  93. h3(tag#mod_keywords_input). mod_keywords_input _(deprecated)_
  94. p(tag-summary). Display a text input field for the keywords.
  95. *(atts) %(atts-name)class% %(atts-type)string% The CSS class name to associate with the outputted HTML tag
  96. * %(atts-name)isize% %(atts-type)int% The size of the input field.
  97. h3(tag#mod_body_input). mod_body_input _(deprecated)_
  98. p(tag-summary). Display a textarea field for the body.
  99. *(atts) %(atts-name)class% %(atts-type)string% The CSS class name to associate with the outputted HTML tag
  100. * %(atts-name)style% %(atts-type)string% The CSS style attribute to apply to the input field.
  101. h3(tag#mod_body_html_input). mod_body_html_input _(deprecated)_
  102. p(tag-summary). Display a textarea field for the body_html.
  103. *(atts) %(atts-name)class% %(atts-type)string% The CSS class name to associate with the outputted HTML tag
  104. * %(atts-name)style% %(atts-type)string% The CSS style attribute to apply to the input field.
  105. h3(tag#mod_excerpt_input). mod_excerpt_input _(deprecated)_
  106. p(tag-summary). Display a textarea field for the excerpt.
  107. *(atts) %(atts-name)class% %(atts-type)string% The CSS class name to associate with the outputted HTML tag
  108. * %(atts-name)style% %(atts-type)string% The CSS style attribute to apply to the input field.
  109. h3(tag#mod_excerpt_html_input). mod_excerpt_html_input _(deprecated)_
  110. p(tag-summary). Display a textarea field for the excerpt_html.
  111. *(atts) %(atts-name)class% %(atts-type)string% The CSS class name to associate with the outputted HTML tag
  112. * %(atts-name)style% %(atts-type)string% The CSS style attribute to apply to the input field.
  113. h3(tag#mod_note_input). mod_note_input _(deprecated)_
  114. p(tag-summary). Display a textarea field for the note (to the moderators)
  115. *(atts) %(atts-name)class% %(atts-type)string% The CSS class name to associate with the outputted HTML tag
  116. * %(atts-name)style% %(atts-type)string% The CSS style attribute to apply to the input field.
  117. # --- END PLUGIN HELP ---
  118. <?php
  119. }
  120. # --- BEGIN PLUGIN CODE ---
  121. ////////////////////////////////////////////////////////////
  122. // Plugin
  123. // Author: Michael Manfre (http://manfre.net/)
  124. ////////////////////////////////////////////////////////////
  125. ////////////////////////////////////////////////////////////
  126. // Do not modify below this line
  127. require_plugin('mem_moderation');
  128. global $event, $step, $prefs, $mem_article_vars, $mem_article_delete_vars, $mem_moderation_lang;
  129. $mem_moderation_lang = array_merge($mem_moderation_lang, array(
  130. 'mem_mod_pub_bypass_queue' => 'Publishers bypass queue delay?',
  131. 'mem_mod_article_edit_resets_time' => 'Edit resets article time?',
  132. 'mem_mod_article_submit_with_moderator_id' => 'Substitute approver as article editor?',
  133. ));
  134. // article/article-edit vars
  135. $mem_article_vars = array('note','user','email','modid','id','articleid',
  136. 'title','title_html','body','body_html','excerpt','excerpt_html','textile_excerpt','image',
  137. 'textile_body','keywords','status','section','category1','category2',
  138. 'annotate','annotateinvite','override_form',
  139. 'custom_1','custom_2','custom_3','custom_4','custom_5',
  140. 'custom_6','custom_7','custom_8','custom_9','custom_10');
  141. // article-delete vars
  142. $mem_article_delete_vars = array('user','email','articleid','title');
  143. // Include the article page when safe to do so
  144. if ((@txpinterface=='admin' and ($event=='moderate' or $event=='article_moderate')) or @txpinterface!='admin')
  145. {
  146. require_once(txpath.'/include/txp_article.php');
  147. }
  148. /** Show a category select list for presenter */
  149. function mem_category_popup($name,$val)
  150. {
  151. $rs = getTree("root",'article');
  152. if ($rs)
  153. {
  154. return treeSelectInput($name,$rs,$val);
  155. }
  156. return false;
  157. }
  158. if (@txpinterface == 'admin')
  159. {
  160. // give publisher install access
  161. add_privs('article_moderate','1');
  162. // register event with txp
  163. register_callback('article_moderate','article_moderate','', 1);
  164. // wire up moderation types
  165. mem_moderation_register('article',$mem_article_vars,'mem_article_presenter','mem_article_approver','mem_article_rejecter');
  166. mem_moderation_register('article-edit',$mem_article_vars,'mem_article_presenter','mem_article_approver','mem_article_rejecter');
  167. mem_moderation_register('article-delete',$mem_article_delete_vars,'mem_article_presenter','mem_article_approver','mem_article_rejecter');
  168. if ($event=='article_moderate')
  169. {
  170. /** Event handler */
  171. function article_moderate($event, $step)
  172. {
  173. $msg='';
  174. if ($step=='article_save' or $step=='article_post')
  175. {
  176. // save changes
  177. $msg = article_save($step);
  178. }
  179. else if ($step=='preinstall' or $step=='install')
  180. {
  181. // need tab during install
  182. register_tab('extensions','article_moderate','article_moderate');
  183. echo pageTop('Article Moderation','');
  184. echo article_install();
  185. return;
  186. }
  187. else
  188. {
  189. trigger_error(gTxt('unknown_step'));
  190. }
  191. pageTop('article Moderation',$msg);
  192. }
  193. /** Install Default Forms, prefs, etc. */
  194. function article_install()
  195. {
  196. global $prefs;
  197. $log = array();
  198. // default article edit form
  199. $form = fetch('Form','txp_form','name','mod_article_form');
  200. if (!$form)
  201. {
  202. $form_html = <<<EOF
  203. <txp:mem_form_text name="title" label="Title" />
  204. <txp:mem_form_select_category name="category1" label="Category" />
  205. <txp:mem_form_textarea name="body" label="Body" />
  206. <txp:mem_form_textarea name="note" label="Notes for the Moderator (optional)" required="0" />
  207. <!-- this will put the submitting username in to custom field 1 -->
  208. <txp:mem_form_hidden name="custom_1" value='<txp:mem_profile var="name" />' />
  209. <div><txp:mem_form_submit /></div>
  210. EOF;
  211. $form_html = doSlash($form_html);
  212. if (safe_insert('txp_form',"name='mod_article_form',type='misc',Form='{$form_html}'"))
  213. $log[] = "Created form 'mod_article_form'";
  214. else
  215. $log[] = "Failed to create form 'mod_article_form'. " . mysql_error();
  216. }
  217. else
  218. {
  219. $log[] = "Found form 'mod_article_form'. Skipping installation of default form.";
  220. }
  221. // default article success form
  222. $form = fetch('Form','txp_form','name','mod_article_success');
  223. if (!$form)
  224. {
  225. $form_html = <<<EOF
  226. <txp:mem_if_step name="article_delete">
  227. <h2>Article deleted</h2>
  228. <p>Your article has been deleted and will not be posted on this site.</p>
  229. <txp:else />
  230. <h2>News submitted</h2>
  231. <p>Thank you for submitting your article. It will be reviewed by a moderator before being posted to the site.</p>
  232. </txp:mem_if_step>
  233. EOF;
  234. $form_html = doSlash($form_html);
  235. if (safe_insert('txp_form',"name='mod_article_success',type='misc',Form='{$form_html}'"))
  236. $log[] = "Created form 'mod_article_form'";
  237. else
  238. $log[] = "Failed to create form 'mod_article_success'. " . mysql_error();
  239. }
  240. else
  241. {
  242. $log[] = "Found form 'mod_article_success'. Skipping installation of default form.";
  243. }
  244. if (!isset($prefs['mem_mod_article_edit_resets_time']))
  245. {
  246. set_pref('mem_mod_article_edit_resets_time', '0', 'mem_moderation', 1, 'yesnoradio');
  247. $log[] = "Set preference mem_mod_article_edit_resets_time";
  248. }
  249. if (!isset($prefs['mem_mod_article_submit_with_moderator_id']))
  250. {
  251. set_pref('mem_mod_article_submit_with_moderator_id', '0', 'mem_moderation', 1, 'yesnoradio');
  252. $log[] = "Set preference mem_mod_article_submit_with_moderator_id";
  253. }
  254. return tag("Install Log",'h2').doWrap($log,'ul','li');
  255. }
  256. } // if article_moderate
  257. } // if admin
  258. /** The article form tag. Handles all logic. Deprecated */
  259. function mod_article_form($atts,$thing='')
  260. {
  261. trigger_error(gTxt('deprecated_function_with', array('{name}' => __FUNCTION__, '{with}' => 'mem_moderation_article_form')), E_USER_NOTICE);
  262. global $step,$txp_user,$ign_user,$mem_mod_info,$mem_modarticle_info, $mem_article_vars;
  263. extract(gpsa(array('modid','action','event','step','id')));
  264. if (!empty($modid)) $id = $modid;
  265. if (isset($ign_user)) $txp_user = $ign_user;
  266. extract(lAtts(array(
  267. 'form' => 'mod_article_form',
  268. 'successform' => 'mod_article_success'
  269. ),$atts));
  270. $mem_modarticle_info = gpsa($mem_article_vars);
  271. if (isset($id))
  272. $mem_modarticle_info['id'] = $id;
  273. extract($mem_modarticle_info);
  274. $out = '';
  275. if (isset($action) and $action==gTxt( 'delete' ))
  276. $step = 'article_delete';
  277. if (isset($step) and ($step=='article_save' or $step=='article_update' or $step=='article_delete'))
  278. {
  279. if (!empty($successform))
  280. $Form = fetch_form($successform);
  281. if ($step=='article_delete')
  282. {
  283. if (remove_moderated_content($modid)) {
  284. $msg = 'Deleted article';
  285. } else {
  286. $msg = 'Failed to delete article image';
  287. }
  288. }
  289. else if ($step=='article_update')
  290. {
  291. if (update_moderated_content($id,$note,$mem_modarticle_info)) {
  292. $res = 'Updated Article';
  293. } else {
  294. $res = 'Failed to update Article';
  295. }
  296. }
  297. else
  298. {
  299. if (!isset($user))
  300. $mem_modarticle_info['user'] = $txp_user;
  301. $res = submit_moderated_content('article','',$mem_modarticle_info['note'],$mem_modarticle_info);
  302. }
  303. $out = admin_parse($Form);
  304. unset($mem_modarticle_info);
  305. }
  306. else
  307. {
  308. if (empty($form))
  309. $Form = $thing;
  310. else
  311. $Form = fetch_form($form);
  312. $action_url = $_SERVER['REQUEST_URI'];
  313. $qs = strpos($action_url,'?');
  314. if ($qs) $action_url = substr($action_url, 0, $qs);
  315. $out = n.n."<form enctype='multipart/form-data' action='{$action_url}' method='post'>" .
  316. eInput('article_moderate') .
  317. sInput( $step=='article_edit' ? 'article_update' : 'article_save' );
  318. if (isset($modid) and !empty($modid))
  319. {
  320. $out .= hInput('modid',$modid);
  321. $mem_mod_info = safe_row('*','txp_moderation',"`id`='".doSlash($modid)."'");
  322. extract($mem_modarticle_info=mem_moderation_decode($mem_mod_info['data']));
  323. }
  324. if (isset($user) and !empty($user))
  325. $out .= hInput('user',$user);
  326. if (isset($email) and !empty($email))
  327. $out .= hInput('email',$email);
  328. else if ($email=safe_field('email','txp_users',"name='".doSlash($user)."'"))
  329. $out .= hInput('email',$email);
  330. $cattree = getTree("root",'article');
  331. $rs = safe_column("name", "txp_section", "name!='default'");
  332. if (!isset($section) || empty($section))
  333. $section = getDefaultSection();
  334. $section_select = ($rs) ? selectInput("section", $rs, $section) : '';
  335. $vals = array(
  336. 'category1_select' => treeSelectInput("category1", $cattree, $category1),
  337. 'category2_select' => treeSelectInput("category2", $cattree, $category2),
  338. 'section_select' => $section_select,
  339. 'submit' => fInput( "submit", 'action', gTxt( 'save' ), "publish" ),
  340. 'delete' => (!empty($modid) ? fInput( "submit", 'action', gTxt( 'delete' ), "delete", '', "return confirm('". gTxt('are_you_sure') ."')" ) : '')
  341. );
  342. foreach ($vals as $a=>$b)
  343. {
  344. $a = '<txp:mod_'.$a.' />';
  345. $Form = str_replace($a,$b,$Form);
  346. }
  347. $out .= parse($Form);
  348. $out .= '</form>'.n;
  349. unset($mem_mod_info);
  350. unset($mem_modarticle_info);
  351. }
  352. return $out;
  353. }
  354. function mod_custom_input($atts)
  355. {
  356. trigger_error(gTxt('deprecated_function_with', array('{name}' => __FUNCTION__, '{with}' => 'mem_form_text')), E_USER_NOTICE);
  357. global $mem_modarticle_info;
  358. extract(lAtts(array(
  359. 'id' => '1',
  360. 'isize' => 25,
  361. 'class' => __FUNCTION__
  362. ),$atts));
  363. $title = $value = $mem_modarticle_info["custom_{$id}"];
  364. return fInput('text',"custom_{$id}",$value,$class,"custom_{$id}",'',$isize,'',"customer-{$id}");
  365. }
  366. function mod_title_input($atts)
  367. {
  368. trigger_error(gTxt('deprecated_function_with', array('{name}' => __FUNCTION__, '{with}' => 'mem_form_text')), E_USER_NOTICE);
  369. global $mem_mod_info,$mem_modarticle_info;
  370. extract(lAtts(array(
  371. 'isize' => 25,
  372. 'class' => __FUNCTION__
  373. ),$atts));
  374. $title = $value = $mem_modarticle_info["title"];
  375. return fInput('text',"title",$value,$class,'title','',$isize);
  376. }
  377. function mod_image_input($atts)
  378. {
  379. trigger_error(gTxt('deprecated_function_with', array('{name}' => __FUNCTION__, '{with}' => 'mem_form_text')), E_USER_NOTICE);
  380. global $mem_mod_info,$mem_modarticle_info;
  381. extract(lAtts(array(
  382. 'isize' => 25,
  383. 'class' => __FUNCTION__
  384. ),$atts));
  385. $title = $value = $mem_modarticle_info["image"];
  386. return fInput('text',"image",$value,$class,'image','',$isize);
  387. }
  388. function mod_keywords_input($atts)
  389. {
  390. trigger_error(gTxt('deprecated_function_with', array('{name}' => __FUNCTION__, '{with}' => 'mem_form_text')), E_USER_NOTICE);
  391. global $mem_mod_info,$mem_modarticle_info;
  392. extract(lAtts(array(
  393. 'isize' => 25,
  394. 'style' => '',
  395. 'class' => __FUNCTION__
  396. ),$atts));
  397. $title = $value = $mem_modarticle_info["keywords"];
  398. return '<textarea name="keywords"'.(!empty($style)?' style="'.$style.'"':'').
  399. (!empty($class)?' class="'.$class.'"':'').'>'.
  400. htmlspecialchars($mem_modarticle_info['keywords']).'</textarea>';
  401. }
  402. function mod_body_input($atts)
  403. {
  404. trigger_error(gTxt('deprecated_function_with', array('{name}' => __FUNCTION__, '{with}' => 'mem_form_textarea')), E_USER_NOTICE);
  405. global $mem_mod_info,$mem_modarticle_info;
  406. extract(lAtts(array(
  407. 'style' => '',
  408. 'class' => __FUNCTION__
  409. ),$atts));
  410. return '<textarea name="body"'.(!empty($style)?' style="'.$style.'"':'').
  411. (!empty($class)?' class="'.$class.'"':'').'>'.
  412. htmlspecialchars($mem_modarticle_info['body']).'</textarea>';
  413. }
  414. function mod_body_html_input($atts)
  415. {
  416. trigger_error(gTxt('deprecated_function_with', array('{name}' => __FUNCTION__, '{with}' => 'mem_form_textarea')), E_USER_NOTICE);
  417. global $mem_mod_info,$mem_modarticle_info;
  418. extract(lAtts(array(
  419. 'style' => '',
  420. 'class' => __FUNCTION__
  421. ),$atts));
  422. return '<textarea name="body_html"'.(!empty($style)?' style="'.$style.'"':'').
  423. (!empty($class)?' class="'.$class.'"':'').'>'.
  424. htmlspecialchars($mem_modarticle_info['body_html']).'</textarea>';
  425. }
  426. function mod_excerpt_input($atts)
  427. {
  428. trigger_error(gTxt('deprecated_function_with', array('{name}' => __FUNCTION__, '{with}' => 'mem_form_textarea')), E_USER_NOTICE);
  429. global $mem_mod_info,$mem_modarticle_info;
  430. extract(lAtts(array(
  431. 'style' => '',
  432. 'class' => __FUNCTION__
  433. ),$atts));
  434. return '<textarea name="excerpt"'.(!empty($style)?' style="'.$style.'"':'').
  435. (!empty($class)?' class="'.$class.'"':'').'>'.
  436. htmlspecialchars($mem_modarticle_info['excerpt']).'</textarea>';
  437. }
  438. function mod_excerpt_html_input($atts)
  439. {
  440. trigger_error(gTxt('deprecated_function_with', array('{name}' => __FUNCTION__, '{with}' => 'mem_form_textarea')), E_USER_NOTICE);
  441. global $mem_mod_info,$mem_modarticle_info;
  442. extract(lAtts(array(
  443. 'style' => '',
  444. 'class' => __FUNCTION__
  445. ),$atts));
  446. return '<textarea name="excerpt_html"'.(!empty($style)?' style="'.$style.'"':'').
  447. (!empty($class)?' class="'.$class.'"':'').'>'.
  448. htmlspecialchars($mem_modarticle_info['excerpt_html']).'</textarea>';
  449. }
  450. /** Article presenter for article* moderation types */
  451. function mem_article_presenter($type,$data)
  452. {
  453. global $mem_article_delete_vars, $prefs;
  454. $out = '';
  455. if (!is_array($data))
  456. {
  457. // no data, no form
  458. return '';
  459. }
  460. extract(get_prefs());
  461. // article and edit actions
  462. if ($type == 'article' || $type == 'article-edit')
  463. {
  464. // defaults
  465. extract(@lAtts(array(
  466. 'user' => '',
  467. 'email' => '',
  468. 'title' => '',
  469. 'title_html' => '',
  470. 'body' => '',
  471. 'body_html' => '',
  472. 'excerpt' => '',
  473. 'excerpt_html' => '',
  474. 'image' => '',
  475. 'keywords' => '',
  476. 'status' => '',
  477. 'section' => getDefaultSection(),
  478. 'category1' => '',
  479. 'category2' => '',
  480. 'annotate' => ($comments_on_default==1 ? 1 : 0),
  481. 'annotateinvite' => $comments_default_invite,
  482. 'override_form' => '',
  483. 'custom_1' => '',
  484. 'custom_2' => '',
  485. 'custom_3' => '',
  486. 'custom_4' => '',
  487. 'custom_5' => '',
  488. 'custom_6' => '',
  489. 'custom_7' => '',
  490. 'custom_8' => '',
  491. 'custom_9' => '',
  492. 'custom_10' => '',
  493. 'custom_11' => '',
  494. 'custom_12' => '',
  495. 'custom_13' => '',
  496. 'custom_14' => '',
  497. 'custom_15' => '',
  498. 'custom_16' => '',
  499. 'custom_17' => '',
  500. 'custom_18' => '',
  501. 'custom_19' => '',
  502. 'custom_20' => '',
  503. 'articleid' => 0
  504. ),$data));
  505. // populate section select
  506. $rs = safe_rows("name, title", "txp_section", "name!='default'");
  507. $section_values = array();
  508. foreach($rs as $r)
  509. {
  510. $section_values[$r['name']] = $r['title'];
  511. }
  512. $section_select = selectInput("section", $section_values, $section);
  513. // show article edit table
  514. $out = startTable( 'edit' ) .
  515. tr( fLabelCell( 'title' ) . fInputCell( 'title', $title, 1, 30 )) .
  516. (empty($section_select) ? '' : tr( fLabelCell( 'section' ) . tda( $section_select ) )) .
  517. tr( fLabelCell( 'categorize' ) . tda( mem_category_popup("category1", $category1) .br. mem_category_popup("category2", $category2) ) ) .
  518. tr( fLabelCell( 'excerpt' ) . tda( '<textarea name="excerpt" cols="40" rows="4">'.$excerpt.'</textarea>', ' valign="top"' ) ) .
  519. tr( fLabelCell( 'body' ) . tda( '<textarea name="body" cols="40" rows="7">'.$body.'</textarea>', ' valign="top"' ) ) .
  520. tr( fLabelCell( 'status' ) . tda( selectInput('status', array(1=>'Draft',2=>'Hidden',3=>'Pending',4=>'Live',5=>'Sticky'),4) ) ) .
  521. tr( fLabelCell( 'image' ) . fInputCell( 'image', $image, 1, 30 )) .
  522. tr( fLabelCell( 'annotate' ) . tda( yesnoRadio('annotate',$annotate) ) ) .
  523. tr( fLabelCell( 'annotateinvite' ) . fInputCell( 'annotateinvite', $annotateinvite, 1, 30 )) .
  524. tr( fLabelCell( 'keywords' ) . fInputCell( 'keywords', $keywords, 1, 30 )) .
  525. tr( fLabelCell( 'override_default_form', '', 'override-form' ) . tda(form_pop($override_form,'override-form').popHelp('override_form'))) .
  526. tr( fLabelCell( 'author' ) . fInputCell( 'user', $user, 1, 30 ));
  527. $custom_fields = safe_rows('name, val, html', 'txp_prefs', "name like 'custom_%_set' and event = 'custom'");
  528. if ($custom_fields)
  529. {
  530. foreach($custom_fields as $field)
  531. {
  532. extract($field);
  533. $tr = fLabelCell( $val );
  534. $k = implode('_', explode('_', $name, -1));
  535. switch ($html)
  536. {
  537. case 'select':
  538. // get values
  539. $items = safe_column('value', 'custom_fields', "name = '{$name}'");
  540. $tr .= tda(
  541. selectInput($k, $items, @$$k),
  542. ' class="noline"'
  543. );
  544. break;
  545. default:
  546. $tr .= fInputCell( $k, @$$k, 1, 30 );
  547. break;
  548. }
  549. $out .= tr($tr);
  550. }
  551. }
  552. else
  553. {
  554. // add custom field forms
  555. for($i=1;$i<=20;$i++) {
  556. $k = "custom_{$i}";
  557. $kset = "custom_{$i}_set";
  558. if (isset($$kset) and !empty($$kset))
  559. {
  560. $out .= tr( fLabelCell( $$kset, '', "custom-{$i}" ) .
  561. fInputCell( $k, $$k, 1, 30,'', "custom-{$i}" ) );
  562. }
  563. }
  564. }
  565. $out .= endTable();
  566. // hidden form fields
  567. $out .= hInput('email',$email);
  568. $out .= hInput('excerpt_html',$excerpt_html);
  569. $out .= hInput('body_html',$body_html);
  570. $out .= hInput('title_html',$title_html);
  571. if ($type == 'article-edit')
  572. {
  573. $out .= hInput('articleid', $articleid);
  574. }
  575. }
  576. else if ($type=='article-delete')
  577. {
  578. extract($data);
  579. // pass through data
  580. foreach ($mem_article_delete_vars as $v)
  581. {
  582. $out .= @hInput($v, $$v);
  583. }
  584. // link to article on write tab
  585. $out .= '<div style="text-align:center;margin-bottom:1em;">The user "'. htmlspecialchars($user) .'" has requested the deletion of article <a href="./index.php?event=article&amp;step=edit&amp;ID='
  586. . $articleid.'">#'. $articleid .': "'. $title .'"</a>.</div>';
  587. }
  588. return $out;
  589. }
  590. /** Moderation Approver.
  591. * article, article-edit = create/update article
  592. * article-delete = delete article
  593. * Returns '' on success, otherwise error string.
  594. */
  595. function mem_article_approver($type, $data)
  596. {
  597. global $txp_user, $prefs;
  598. if (!is_array($data))
  599. {
  600. // cannot approve
  601. return 'invalid data';
  602. }
  603. $data = array_merge(array(
  604. 'annotateinvite' => '',
  605. 'image' => '',
  606. 'status' => 4,
  607. 'category1' => '',
  608. 'category2' => '',
  609. 'override_form' => '',
  610. 'keywords' => '',
  611. 'custom_1' => '',
  612. 'custom_2' => '',
  613. 'custom_3' => '',
  614. 'custom_4' => '',
  615. 'custom_5' => '',
  616. 'custom_6' => '',
  617. 'custom_7' => '',
  618. 'custom_8' => '',
  619. 'custom_9' => '',
  620. 'custom_10' => '',
  621. 'url_title' => '',
  622. 'textile_body' => '1',
  623. 'textile_excerpt' => '1',
  624. ), $data);
  625. if ($type=='article')
  626. {
  627. $incoming = $data;
  628. extract(get_prefs());
  629. $message='';
  630. // remap field values
  631. $incoming['Status'] = $incoming['status'];
  632. $incoming['Title'] = $incoming['title'];
  633. $incoming['Body'] = $incoming['body'];
  634. $incoming['Excerpt'] = $incoming['excerpt'];
  635. $incoming['publish_now'] = 1;
  636. $use_textile = 1; // this does nothing see #32
  637. $incoming = textile_main_fields($incoming, $use_textile);
  638. extract(doSlash($incoming));
  639. if ( @$mem_mod_article_submit_with_moderator_id || !isset($user) ) {
  640. $user = $txp_user;
  641. }
  642. // article time
  643. if ($publish_now==1)
  644. {
  645. $when = 'now()';
  646. }
  647. else
  648. {
  649. $when = strtotime($year.'-'.$month.'-'.$day.' '.$hour.':'.$minute.":00")-tz_offset();
  650. $when = "from_unixtime($when)";
  651. }
  652. if ($Title or $Body or $Excerpt)
  653. {
  654. // enforce article publishing privs
  655. if (!has_privs('article.publish') && $Status>=4) $Status = 3;
  656. if (@empty($url_title)) $url_title = stripSpace($Title_plain, 1);
  657. if (!$annotate) {
  658. $annotate = $comments_on_default;
  659. }
  660. if (empty($annotateinvite)) $annotateinvite = $comments_default_invite;
  661. $use_textile = $prefs['use_textile'];
  662. if (empty($textile_excerpt))
  663. {
  664. $textile_excerpt = !empty($use_textile) ? $use_textile : '0';
  665. }
  666. if (empty($textile_body))
  667. {
  668. $textile_body = !empty($use_textile) ? $use_textile : '0';
  669. }
  670. $rs = safe_insert(
  671. "textpattern",
  672. "Title = '$Title',
  673. Body = '$Body',
  674. Body_html = '$Body_html',
  675. Excerpt = '$Excerpt',
  676. Excerpt_html = '$Excerpt_html',
  677. Image = '$image',
  678. Keywords = '$keywords',
  679. Status = '$Status',
  680. Posted = $when,
  681. LastMod = now(),
  682. AuthorID = '$user',
  683. Section = '$section',
  684. Category1 = '$category1',
  685. Category2 = '$category2',
  686. textile_body = $textile_body,
  687. textile_excerpt = $textile_excerpt,
  688. Annotate = '$annotate',
  689. override_form = '$override_form',
  690. url_title = '$url_title',
  691. AnnotateInvite = '$annotateinvite',
  692. custom_1 = '$custom_1',
  693. custom_2 = '$custom_2',
  694. custom_3 = '$custom_3',
  695. custom_4 = '$custom_4',
  696. custom_5 = '$custom_5',
  697. custom_6 = '$custom_6',
  698. custom_7 = '$custom_7',
  699. custom_8 = '$custom_8',
  700. custom_9 = '$custom_9',
  701. custom_10 = '$custom_10',
  702. uid = '".md5(uniqid(rand(),true))."',
  703. feed_time = now()"
  704. );
  705. if ($rs !== false)
  706. {
  707. $GLOBALS['ID'] = mysql_insert_id();
  708. // ping on publish
  709. if ($Status>=4)
  710. {
  711. do_pings();
  712. safe_update("txp_prefs", "val = now()", "name = 'lastmod'");
  713. }
  714. }
  715. else
  716. {
  717. return 'error ('.mysql_errno().') - '. mysql_error();
  718. }
  719. }
  720. else
  721. {
  722. return 'missing title, body, and excerpt';
  723. }
  724. }
  725. else if ($type=='article-edit')
  726. {
  727. $incoming = $data;
  728. if (!isset($incoming['articleid']) || empty($incoming['articleid']))
  729. {
  730. return 'Article id not provided.';
  731. }
  732. extract(get_prefs());
  733. $message='';
  734. // remap field values
  735. $incoming['Status'] = $incoming['status'];
  736. $incoming['Title'] = $incoming['title'];
  737. $incoming['Body'] = $incoming['body'];
  738. $incoming['Excerpt'] = $incoming['excerpt'];
  739. $incoming['Image'] = $incoming['image'];
  740. $oldArticle = safe_row('*','textpattern','ID = '.(int)$incoming['articleid']);
  741. if ($oldArticle === false)
  742. {
  743. return 'Article '. $incoming['articleid'].' not found.';
  744. }
  745. // authorize
  746. if (! ( ($oldArticle['Status'] >= 4 and has_privs('article.edit.published'))
  747. or ($oldArticle['Status'] >= 4 and $incoming['AuthorID']==$txp_user and has_privs('article.edit.own.published'))
  748. or ($oldArticle['Status'] < 4 and has_privs('article.edit'))
  749. or ($oldArticle['Status'] < 4 and $incoming['AuthorID']==$txp_user and has_privs('article.edit.own'))))
  750. {
  751. // Not allowed, you silly rabbit, you shouldn't even be here.
  752. // Show default editing screen.
  753. return 'Access denied.';
  754. }
  755. $use_textile = 1; // this does nothing see #32
  756. $incoming = textile_main_fields($incoming, $use_textile);
  757. extract(doSlash($incoming));
  758. // use existing for defaults
  759. extract(doSlash($oldArticle), EXTR_SKIP);
  760. $Status = assert_int($Status);
  761. $ID = assert_int($articleid);
  762. // override submitter with moderator?
  763. if (@$mem_mod_article_submit_with_moderator_id || !isset($user) )
  764. {
  765. $user = $txp_user;
  766. }
  767. $Annotate = (int) $Annotate;
  768. if (!has_privs('article.publish') && $Status>=4) $Status = 3;
  769. if (@$mem_mod_article_edit_resets_time)
  770. {
  771. $whenposted = ",Posted=now()";
  772. }
  773. else
  774. {
  775. $whenposted = '';
  776. }
  777. //Auto-Update custom-titles according to Title, as long as unpublished and NOT customized
  778. if ( empty($url_title)
  779. || ( ($oldArticle['Status'] < 4)
  780. && ($oldArticle['url_title'] == $url_title )
  781. && ($oldArticle['url_title'] == stripSpace($oldArticle['Title'],1))
  782. && ($oldArticle['Title'] != $Title)
  783. )
  784. )
  785. {
  786. $url_title = stripSpace($Title_plain, 1);
  787. }
  788. $Keywords = doSlash(trim(preg_replace('/( ?[\r\n\t,])+ ?/s', ',', preg_replace('/ +/', ' ', $keywords)), ', '));
  789. $use_textile = $prefs['use_textile'];
  790. if (empty($textile_excerpt))
  791. {
  792. $textile_excerpt = !empty($use_textile) ? $use_textile : '0';
  793. }
  794. if (empty($textile_body))
  795. {
  796. $textile_body = !empty($use_textile) ? $use_textile : '0';
  797. }
  798. $rs = safe_update("textpattern",
  799. "Title = '$Title',
  800. Body = '$Body',
  801. Body_html = '$Body_html',
  802. Excerpt = '$Excerpt',
  803. Excerpt_html = '$Excerpt_html',
  804. Keywords = '$Keywords',
  805. Image = '$Image',
  806. Status = $Status,
  807. LastMod = now(),
  808. LastModID = '$user',
  809. Section = '$Section',
  810. Category1 = '$Category1',
  811. Category2 = '$Category2',
  812. Annotate = $Annotate,
  813. textile_body = $textile_body,
  814. textile_excerpt = $textile_excerpt,
  815. override_form = '$override_form',
  816. url_title = '$url_title',
  817. AnnotateInvite = '$AnnotateInvite',
  818. custom_1 = '$custom_1',
  819. custom_2 = '$custom_2',
  820. custom_3 = '$custom_3',
  821. custom_4 = '$custom_4',
  822. custom_5 = '$custom_5',
  823. custom_6 = '$custom_6',
  824. custom_7 = '$custom_7',
  825. custom_8 = '$custom_8',
  826. custom_9 = '$custom_9',
  827. custom_10 = '$custom_10'
  828. $whenposted",
  829. "ID = $ID"
  830. );
  831. if ($rs)
  832. {
  833. $GLOBALS['ID'] = $ID;
  834. }
  835. if($Status >= 4)
  836. {
  837. // only ping on first publish
  838. if ($oldArticle['Status'] < 4) {
  839. do_pings();
  840. }
  841. update_lastmod();
  842. }
  843. return ($rs ? '' : get_status_message($Status).check_url_title($url_title));
  844. }
  845. else if ($type=='article-delete')
  846. {
  847. // make sure the mod is allowed to delete
  848. if (!has_privs('article.delete'))
  849. {
  850. return 'You lack the required privileges to moderate this article.';
  851. }
  852. extract($data);
  853. if (isset($articleid))
  854. {
  855. $id = assert_int($articleid);
  856. // delete article
  857. if (safe_delete('textpattern', "ID = $id"))
  858. {
  859. // hide comments associated with deleted article
  860. safe_update('txp_discuss', "visible = ".MODERATE, "parentid = {$id}");
  861. }
  862. else
  863. {
  864. return 'failed to delete article';
  865. }
  866. }
  867. else
  868. {
  869. return 'invalid article id';
  870. }
  871. }
  872. else
  873. {
  874. return "invalid type {$type}";
  875. }
  876. }
  877. function mem_article_rejecter($type,$data)
  878. {
  879. // if ($type=='article' and is_array($data)) {
  880. // // do nothing
  881. // }
  882. }
  883. /** HTML select populated with categories. Default section is
  884. * pulled from GET/POST.
  885. */
  886. function mem_gps_category($atts)
  887. {
  888. extract(lAtts(array(
  889. 'arg' => 'category1',
  890. 'link' => 0,
  891. 'title' => 1,
  892. 'section' => gps('section'),
  893. 'wraptag' => '',
  894. ),$atts));
  895. return category(array(
  896. 'link' => $link,
  897. 'title' => $title,
  898. 'name' => gps($arg),
  899. 'wraptag' => $wraptag,
  900. 'section' => $section
  901. ));
  902. }
  903. /** HTML select populated with sections. Default section is
  904. * pulled from GET/POST.
  905. */
  906. function mem_gps_section($atts)
  907. {
  908. extract(lAtts(array(
  909. 'arg' => 'section',
  910. 'link' => 0,
  911. 'title' => 1,
  912. 'wraptag' => '',
  913. ),$atts));
  914. return section(array(
  915. 'link' => $link,
  916. 'title' => $title,
  917. 'name' => gps($arg),
  918. 'wraptag' => $wraptag
  919. ));
  920. }
  921. /** Put delete listener on a page. Links from
  922. * mem_article_action_link should point here.
  923. */
  924. function mem_article_delete_sentry($atts,$thing='')
  925. {
  926. global $txp_user,$ign_user,$mem_mod_article_delete_requested;
  927. extract(lAtts(array(
  928. 'successmsg' => 'Submitted request',
  929. 'failuremsg' => 'Failed to submit request',
  930. 'wraptag' => '',
  931. 'class' => ''
  932. ),$atts));
  933. if (empty($txp_user))
  934. {
  935. // user not set, try ign plugin
  936. $txp_user = @$ign_user;
  937. }
  938. $hash = gps('h');
  939. $articleid = gps('articleid');
  940. $request = gps('request_article_deletion');
  941. if (empty($hash) || empty($articleid) || empty($request))
  942. {
  943. // not a delete request
  944. return '';
  945. }
  946. // get the article title for the hash
  947. $title = safe_field('Title','textpattern',"ID = " . assert_int($articleid));
  948. $nhash = md5($articleid.$title);
  949. if ( $nhash == $hash && $request == '1' )
  950. {
  951. // set flag to hide delete links
  952. $mem_mod_article_delete_requested = true;
  953. $data = array(
  954. 'articleid' => $articleid,
  955. 'title' => $title,
  956. 'user' => $txp_user
  957. );
  958. // push delete action to queue
  959. $res = submit_moderated_content('article-delete','','article-delete: #'.$articleid.' - '.$title,$data, $articleid);
  960. if ($res)
  961. {
  962. // delete all other pending article moderation actions by this user for the same item_id
  963. safe_delete('txp_moderation', "`type` LIKE 'article%' and user = '$txp_user' and item_id = $articleid and id != $res and item_id != 0");
  964. return doTag($successmsg, $wraptag, $class);
  965. }
  966. else
  967. {
  968. // failed to create mod action
  969. return doTag($failuremsg, $wraptag, $class);
  970. }
  971. }
  972. // no delete
  973. return '';
  974. }
  975. /** Tag shows delete link. Delete handled by sentry */
  976. function mem_article_action_link($atts,$thing='')
  977. {
  978. global $thisarticle,$mem_mod_article_delete_requested;
  979. extract(lAtts(array(
  980. 'action' => 'delete',
  981. 'text' => '',
  982. 'url' => '',
  983. 'mode' => '',
  984. 'prompt' => '',
  985. ),$atts));
  986. $action = strtolower($action);
  987. if (empty($text))
  988. $text = mem_moderation_gTxt($action);
  989. if (empty($url))
  990. {
  991. // use current
  992. $url = $_SERVER['REQUEST_URI'];
  993. }
  994. else
  995. {
  996. // make absolute
  997. $url = hu.ltrim($url, '/');
  998. }
  999. // build up GET
  1000. $url .= (strpos($url,'?') === FALSE ? '?' : '&');
  1001. $article_id = $thisarticle['thisid'];
  1002. if ($action == 'delete')
  1003. {
  1004. if (empty($prompt))
  1005. {
  1006. $prompt = 'Are you sure that you want to delete this article?';
  1007. }
  1008. if ($mem_mod_article_delete_requested === true)
  1009. {
  1010. // sentry is acting
  1011. return '';
  1012. }
  1013. $url .= 'articleid='. $article_id .'&request_article_deletion=1&h=' . md5($article_id.$thisarticle['title']);
  1014. }
  1015. else if ($action == 'edit')
  1016. {
  1017. $url .= 'articleid='.$thisarticle['thisid'];
  1018. }
  1019. // output mode
  1020. if ($mode == 'url_only')
  1021. {
  1022. $out = $url;
  1023. }
  1024. else if ($mode == 'url_encoded')
  1025. {
  1026. $out = urlencode($url);
  1027. }
  1028. else if ($mode == 'url_escaped')
  1029. {
  1030. $out = htmlspecialchars($url);
  1031. }
  1032. else
  1033. {
  1034. $out = '<a href="'.htmlspecialchars($url).
  1035. (!empty($prompt) ? "\" onclick=\"javascript:return confirm('{$prompt}');\"" : '').
  1036. '">'. htmlspecialchars($text).'</a>';
  1037. }
  1038. return $out;
  1039. }
  1040. /** Conditional tag. Supports $thisarticle */
  1041. function mem_if_owns_article($atts,$thing='')
  1042. {
  1043. global $thisarticle, $txp_user, $ign_user;
  1044. extract(lAtts(array(
  1045. 'useridfield' => 'AuthorID',
  1046. ),$atts));
  1047. // use ign if needed
  1048. if (empty($txp_user)) $txp_user = $ign_user;
  1049. $cond = is_array($thisarticle) and isset($thisarticle[$articlefield]) and $thisarticle[$articlefield] == $txp_user;
  1050. return parse(EvalElse($thing,$cond));
  1051. }
  1052. function mem_if_article_delete_pending($atts, $thing='')
  1053. {
  1054. global $thisarticle;
  1055. static $pending_ids = false;
  1056. if (empty($pending_ids))
  1057. {
  1058. // get every delete request
  1059. $pending_ids = safe_column('item_id', 'txp_moderation', "type = 'article-delete'");
  1060. // prevent more db calls if there are no delete requests
  1061. if (empty($pending_ids))
  1062. $pending_ids = true;
  1063. }
  1064. $cond = is_array($pending_ids) && in_array($thisarticle['thisid'], $pending_ids);
  1065. return parse(EvalElse($thing, $cond));
  1066. }
  1067. /** custom_article that filters based upon current user (txp or ign) */
  1068. function mem_custom_user_article_list($atts, $thing='')
  1069. {
  1070. global $pretext, $prefs, $txp_user,$ign_user;
  1071. // need url info and txp prefs
  1072. extract($pretext);
  1073. extract($prefs);
  1074. // custom fields and titles
  1075. //$customFields = getCustomFields();
  1076. $customlAtts = array(); //array_null(array_flip($customFields));
  1077. // need a user
  1078. $userid = isset($txp_user) ? @$txp_user : @$ign_user;
  1079. //getting attributes
  1080. $theAtts = lAtts(array(
  1081. 'useridfield' => '',
  1082. 'form' => 'default',
  1083. 'limit' => 10,
  1084. 'offset' => 0,
  1085. 'pageby' => '',
  1086. 'category' => '',
  1087. 'section' => '',
  1088. 'author' => '',
  1089. 'sort' => 'Posted desc',
  1090. 'time' => 'past',
  1091. 'month' => '',
  1092. 'status' => '4',
  1093. )+$customlAtts,$atts);
  1094. extract($theAtts);
  1095. $pageby = (empty($pageby) ? $limit : $pageby);
  1096. // treat sticky articles differently wrt search filtering, etc
  1097. if (!is_numeric($status))
  1098. {
  1099. $status = getStatusNum($status);
  1100. }
  1101. $issticky = ($status == 5);
  1102. $match = $search = '';
  1103. //Building query parts
  1104. $category = join("','", doSlash(do_list($category)));
  1105. $category = (!$category) ? '' : " and (Category1 IN ('".$category."') or Category2 IN ('".$category."'))";
  1106. $section = (!$section) ? '' : " and Section IN ('".join("','", doSlash(do_list($section)))."')";
  1107. $author = (!$author) ? '' : " and AuthorID IN ('".join("','", doSlash(do_list($author)))."')";
  1108. $month = (!$month) ? '' : " and Posted like '".doSlash($month)."%'";
  1109. switch ($time) {
  1110. case 'any':
  1111. $time = ""; break;
  1112. case 'future':
  1113. $time = " and Posted > now()"; break;
  1114. default:
  1115. $time = " and Posted <= now()";
  1116. }
  1117. $custom = '';
  1118. if ($useridfield)
  1119. {
  1120. $custom .= ' and '. doSlash($useridfield) ."='{$userid}' ";
  1121. }
  1122. $statusq = ' and Status = '.intval($status);
  1123. // composit parts
  1124. $where = "1=1" . $statusq. $time.
  1125. $category . $section . $month . $author . $custom ;
  1126. $offset = assert_int($offset);
  1127. $limit = assert_int($limit);
  1128. $rs = safe_rows_start("*, unix_timestamp(Posted) as uPosted, unix_timestamp(Expires) as uExpires, unix_timestamp(LastMod) as uLastMod".$match, 'textpattern',
  1129. $where.' order by '.doSlash($sort).' limit '.$offset.', '.$limit);
  1130. if ($rs)
  1131. {
  1132. $count = 0;
  1133. $articles = array();
  1134. while($a = nextRow($rs))
  1135. {
  1136. ++$count;
  1137. populateArticleData($a);
  1138. global $thisarticle, $uPosted, $limit;
  1139. $thisarticle['is_first'] = ($count == 1);
  1140. $thisarticle['is_last'] = ($count == numRows($rs));
  1141. // uncomment for article_entry patch
  1142. //callback_event('article_entry','list');
  1143. if (isset($GLOBALS['thisarticle']))
  1144. {
  1145. // enclosed > form
  1146. $articles[] = !empty($thing) ? parse($thing) : parse_form($form);
  1147. // sending these to paging_link(); Required?
  1148. $uPosted = $a['uPosted'];
  1149. // clean up
  1150. unset($GLOBALS['thisarticle']);
  1151. }
  1152. }
  1153. return join('',$articles);
  1154. }
  1155. }
  1156. //////////////////////////////////////////////////////
  1157. // Public form methods
  1158. /** Helper tag for mem_form */
  1159. function mem_moderation_article_form($atts, $thing='')
  1160. {
  1161. $atts['type'] = 'mem_moderation_article';
  1162. return mem_form($atts, $thing);
  1163. }
  1164. // register functions with mem_form
  1165. register_callback('mem_mod_article_form_defaults', 'mem_form.defaults');
  1166. register_callback('mem_mod_article_form_display', 'mem_form.display');
  1167. register_callback('mem_mod_article_form_submitted', 'mem_form.submit');
  1168. /** Set form defaults */
  1169. function mem_mod_article_form_defaults()
  1170. {
  1171. global $mem_form, $mem_form_type, $mem_form_default, $mem_mod_info, $mem_modarticle_info;
  1172. // type check
  1173. if ($mem_form_type!='mem_moderation_article')
  1174. {
  1175. return;
  1176. }
  1177. extract(gpsa(array('modid','articleid')));
  1178. // editing mod item
  1179. if (!empty($modid))
  1180. {
  1181. // get mod data
  1182. $mem_mod_info = safe_row('*','txp_moderation',"`id`='".doSlash($modid)."'");
  1183. if ($mem_mod_info)
  1184. {
  1185. // set decoded
  1186. $mem_modarticle_info = mem_moderation_decode($mem_mod_info['data']);
  1187. }
  1188. }
  1189. // editing publish article
  1190. else if (!empty($articleid))
  1191. {
  1192. $rs = safe_row('*', 'textpattern',"`id`='".doSlash($articleid)."'");
  1193. // set mod data
  1194. $mem_modarticle_info = array();
  1195. foreach($rs as $k => $v)
  1196. {
  1197. $mem_modarticle_info[strtolower($k)] = $v;
  1198. }
  1199. }
  1200. if (is_array($mem_modarticle_info))
  1201. {
  1202. // set defaults
  1203. foreach($mem_modarticle_info as $key => $val)
  1204. {
  1205. mem_form_default($key, $val);
  1206. }
  1207. }
  1208. }
  1209. function mem_mod_article_form_display()
  1210. {
  1211. global $mem_form_type, $mem_form_labels, $mem_form_values, $mem_mod_info, $mem_modarticle_info;
  1212. // type check
  1213. if ($mem_form_type!='mem_moderation_article')
  1214. {
  1215. return;
  1216. }
  1217. $out = '';
  1218. if (isset($mem_mod_info))
  1219. {
  1220. $out .= n.'<input type="hidden" name="modid" value="'.htmlspecialchars($mem_mod_info['id']).'" />'.
  1221. n.'<input type="hidden" name="type" value="'. htmlspecialchars($mem_mod_info['type']).'" />';
  1222. if ($mem_mod_info['type'] == 'article-edit' && isset($mem_modarticle_info['articleid']))
  1223. $out .= n.'<input type="hidden" name="articleid" value="'.$mem_modarticle_info['articleid'].'" />';
  1224. mem_form_store('modid', 'modid', $mem_mod_info['id']);
  1225. mem_form_store('type', 'type', $mem_mod_info['type']);
  1226. }
  1227. else if (isset($mem_modarticle_info))
  1228. {
  1229. $out .= n.'<input type="hidden" name="articleid" value="'.htmlspecialchars($mem_modarticle_info['articleid']).'" />'.
  1230. n.'<input type="hidden" name="type" value="article" />';
  1231. }
  1232. return $out;
  1233. }
  1234. /** Form submit handler */
  1235. function mem_mod_article_form_submitted()
  1236. {
  1237. global $prefs, $mem_article_vars, $mem_form_type, $txp_user, $ign_user, $mem_mod_info, $mem_modarticle_info, $mem_form_thanks_form;
  1238. if ($mem_form_type!='mem_moderation_article')
  1239. {
  1240. return;
  1241. }
  1242. extract(gpsa(array('modid','step','id','articleid')));
  1243. $mem_modarticle_info = gpsa($mem_article_vars);
  1244. $out = '';
  1245. $is_save = ps('mem_moderation_save');
  1246. $is_delete = ps('mem_moderation_delete');
  1247. $is_update = ps('mem_moderation_update') || ($is_save && ps('modid'));
  1248. if (isset($ign_user)) $txp_user = $ign_user;
  1249. if (!empty($modid)) $id = $modid;
  1250. if ($is_delete)
  1251. {
  1252. if (remove_moderated_content($modid))
  1253. {
  1254. $res = mem_moderation_gTxt('article_deleted');
  1255. }
  1256. else
  1257. {
  1258. $res = mem_moderation_gTxt('article_delete_failed');
  1259. }
  1260. }
  1261. elseif (!empty($articleid))
  1262. {
  1263. $articleid = doSlash($articleid);
  1264. $rs = safe_rows("*, unix_timestamp(Posted) as uPosted","textpattern","`ID` = $articleid");
  1265. if ($rs)
  1266. {
  1267. // merge the passed in values to the existing
  1268. foreach($mem_modarticle_info as $key => $val)
  1269. {
  1270. $rs[$key] = $val;
  1271. }
  1272. $rs['articleid'] = $articleid;
  1273. if ($is_update)
  1274. {
  1275. $res = update_moderated_content($id, $mem_modarticle_info['note'], $mem_modarticle_info);
  1276. }
  1277. else
  1278. {
  1279. $res = submit_moderated_content('article-edit', $user_email, $mem_modarticle_info['note'], $mem_modarticle_info, $articleid);
  1280. if ($res)
  1281. {
  1282. // delete all other pending article moderation actions by this user for the same item_id
  1283. safe_delete('txp_moderation', "`type` LIKE 'article%' and user = '$txp_user' and item_id = $articleid and id != $res and item_id != 0");
  1284. }
  1285. }
  1286. } // if $rs
  1287. }
  1288. else
  1289. {
  1290. if (isset($id)) $mem_modarticle_info['id'] = $id;
  1291. if ($is_update)
  1292. {
  1293. if (isset($mem_modarticle_info['note']))
  1294. {
  1295. $note = $mem_modarticle_info['note'];
  1296. }
  1297. else
  1298. {
  1299. $note = $mem_mod_info['desc'];
  1300. }
  1301. if (update_moderated_content($id,$note,$mem_modarticle_info))
  1302. {
  1303. $res = mem_moderation_gTxt('article_updated');
  1304. }
  1305. else
  1306. {
  1307. $res = mem_moderation_gTxt('article_update_failed');
  1308. }
  1309. }
  1310. else
  1311. {
  1312. if (!isset($user))
  1313. {
  1314. $mem_modarticle_info['user'] = $txp_user;
  1315. }
  1316. $res = submit_moderated_content('article', '', $mem_modarticle_info['note'], $mem_modarticle_info);
  1317. }
  1318. }
  1319. $mem_modarticle_info['result'] = $res;
  1320. $thanks_form = @fetch_form($mem_form_thanks_form);
  1321. if (!empty($thanks_form))
  1322. {
  1323. $out = parse($thanks_form);
  1324. }
  1325. // cleanup global
  1326. unset($mem_modarticle_info);
  1327. return $out;
  1328. }
  1329. # --- END PLUGIN CODE ---
  1330. ?>