PageRenderTime 42ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/sources/controllers/Drafts.controller.php

https://github.com/Arantor/Elkarte
PHP | 620 lines | 391 code | 88 blank | 141 comment | 82 complexity | c26848f1a0a063cf70f8e80ea1164b0f MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-3.0
  1. <?php
  2. /**
  3. * @name ElkArte Forum
  4. * @copyright ElkArte Forum contributors
  5. * @license BSD http://opensource.org/licenses/BSD-3-Clause
  6. *
  7. * @version 1.0 Alpha
  8. *
  9. * This file contains all the functions that allow for the saving,
  10. * retrieving, deleting and settings for the drafts function.
  11. *
  12. */
  13. if (!defined('ELKARTE'))
  14. die('No access...');
  15. // language and helper functions
  16. loadLanguage('Drafts');
  17. require_once(SUBSDIR . '/Drafts.subs.php');
  18. /**
  19. * Saves a post draft in the user_drafts table
  20. * The core draft feature must be enabled, as well as the post draft option
  21. * Determines if this is a new or an existing draft
  22. *
  23. * @return boolean
  24. */
  25. function saveDraft()
  26. {
  27. global $context, $user_info, $smcFunc, $modSettings, $board;
  28. // ajax calling
  29. if (!isset($context['drafts_save']))
  30. $context['drafts_save'] = !empty($modSettings['drafts_enabled']) && !empty($modSettings['drafts_post_enabled']) && allowedTo('post_draft');
  31. // can you be, should you be ... here?
  32. if (empty($context['drafts_save']) || !isset($_POST['save_draft']) || !isset($_POST['id_draft']))
  33. return false;
  34. // read in what they sent, if anything
  35. $id_draft = empty($_POST['id_draft']) ? 0 : (int) $_POST['id_draft'];
  36. $draft_info = loadDraft($id_draft);
  37. // If a draft has been saved less than 5 seconds ago, let's not do the autosave again
  38. if (isset($_REQUEST['xml']) && !empty($draft_info['poster_time']) && time() < $draft_info['poster_time'] + 5)
  39. {
  40. // since we were called from the autosave function, send something back
  41. if (!empty($id_draft))
  42. {
  43. loadTemplate('Xml');
  44. $context['sub_template'] = 'xml_draft';
  45. $context['id_draft'] = $id_draft;
  46. $context['draft_saved_on'] = $draft_info['poster_time'];
  47. obExit();
  48. }
  49. return;
  50. }
  51. // be ready for surprises
  52. $post_errors = error_context::context('post', 1);
  53. // prepare and clean the data, load the draft array
  54. $draft['id_draft'] = $id_draft;
  55. $draft['topic_id'] = empty($_REQUEST['topic']) ? 0 : (int) $_REQUEST['topic'];
  56. $draft['board'] = $board;
  57. $draft['icon'] = empty($_POST['icon']) ? 'xx' : preg_replace('~[\./\\\\*:"\'<>]~', '', $_POST['icon']);
  58. $draft['smileys_enabled'] = isset($_POST['ns']) ? (int) $_POST['ns'] : 0;
  59. $draft['locked'] = isset($_POST['lock']) ? (int) $_POST['lock'] : 0;
  60. $draft['sticky'] = isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics']) ? (int) $_POST['sticky'] : 0;
  61. $draft['subject'] = strtr($smcFunc['htmlspecialchars']($_POST['subject']), array("\r" => '', "\n" => '', "\t" => ''));
  62. $draft['body'] = $smcFunc['htmlspecialchars']($_POST['message'], ENT_QUOTES);
  63. $draft['id_member'] = $user_info['id'];
  64. // the message and subject still need a bit more work
  65. preparsecode($draft['body']);
  66. if ($smcFunc['strlen']($draft['subject']) > 100)
  67. $draft['subject'] = $smcFunc['substr']($draft['subject'], 0, 100);
  68. // Modifying an existing draft, like hitting the save draft button or autosave enabled?
  69. if (!empty($id_draft) && !empty($draft_info) && $draft_info['id_member'] == $user_info['id'])
  70. {
  71. modify_post_draft($draft);
  72. // some items to return to the form
  73. $context['draft_saved'] = true;
  74. $context['id_draft'] = $id_draft;
  75. }
  76. // otherwise creating a new draft
  77. else
  78. {
  79. $id_draft = create_post_draft($draft);
  80. // everything go as expected?
  81. if (!empty($id_draft))
  82. {
  83. $context['draft_saved'] = true;
  84. $context['id_draft'] = $id_draft;
  85. }
  86. else
  87. $post_errors->addError('draft_not_saved');
  88. }
  89. // cleanup
  90. unset($_POST['save_draft']);
  91. // if we were called from the autosave function, send something back
  92. if (!empty($id_draft) && isset($_REQUEST['xml']) && !$post_errors->hasError('session_timeout'))
  93. {
  94. loadTemplate('Xml');
  95. $context['sub_template'] = 'xml_draft';
  96. $context['id_draft'] = $id_draft;
  97. $context['draft_saved_on'] = time();
  98. obExit();
  99. }
  100. return;
  101. }
  102. /**
  103. * Saves a PM draft in the user_drafts table
  104. * The core draft feature must be enabled, as well as the pm draft option
  105. * Determines if this is a new or and update to an existing pm draft
  106. *
  107. * @param string $post_errors
  108. * @param type $recipientList
  109. * @return boolean
  110. */
  111. function savePMDraft($recipientList)
  112. {
  113. global $context, $user_info, $smcFunc, $modSettings;
  114. // ajax calling
  115. if (!isset($context['drafts_pm_save']))
  116. $context['drafts_pm_save'] = !empty($modSettings['drafts_enabled']) && !empty($modSettings['drafts_pm_enabled']) && allowedTo('pm_draft');
  117. // PM survey says ... can you stay or must you go
  118. if (empty($context['drafts_pm_save']) || !isset($_POST['save_draft']) || !isset($_POST['id_pm_draft']))
  119. return false;
  120. // read in what was sent
  121. $id_pm_draft = empty($_POST['id_pm_draft']) ? 0 : (int) $_POST['id_pm_draft'];
  122. $draft_info = loadDraft($id_pm_draft, 1);
  123. $post_errors = error_context::context('pm', 1);
  124. // 5 seconds is the same limit we have for posting
  125. if (isset($_REQUEST['xml']) && !empty($draft_info['poster_time']) && time() < $draft_info['poster_time'] + 5)
  126. {
  127. // Send something back to the javascript caller
  128. if (!empty($id_pm_draft))
  129. {
  130. loadTemplate('Xml');
  131. $context['sub_template'] = 'xml_draft';
  132. $context['id_draft'] = $id_pm_draft;
  133. $context['draft_saved_on'] = $draft_info['poster_time'];
  134. obExit();
  135. }
  136. return true;
  137. }
  138. // determine who this is being sent to
  139. if (isset($_REQUEST['xml']))
  140. {
  141. $recipientList['to'] = isset($_POST['recipient_to']) ? explode(',', $_POST['recipient_to']) : array();
  142. $recipientList['bcc'] = isset($_POST['recipient_bcc']) ? explode(',', $_POST['recipient_bcc']) : array();
  143. }
  144. elseif (!empty($draft_info['to_list']) && empty($recipientList))
  145. $recipientList = unserialize($draft_info['to_list']);
  146. // prepare the data
  147. $draft['id_pm_draft'] = $id_pm_draft;
  148. $draft['reply_id'] = empty($_POST['replied_to']) ? 0 : (int) $_POST['replied_to'];
  149. $draft['outbox'] = empty($_POST['outbox']) ? 0 : 1;
  150. $draft['body'] = $smcFunc['htmlspecialchars']($_POST['message'], ENT_QUOTES);
  151. $draft['subject'] = strtr($smcFunc['htmlspecialchars']($_POST['subject']), array("\r" => '', "\n" => '', "\t" => ''));
  152. $draft['id_member'] = $user_info['id'];
  153. // message and subject always need a bit more work
  154. preparsecode($draft['body']);
  155. if ($smcFunc['strlen']($draft['subject']) > 100)
  156. $draft['subject'] = $smcFunc['substr']($draft['subject'], 0, 100);
  157. // Modifying an existing PM draft?
  158. if (!empty($id_pm_draft) && !empty($draft_info) && $draft_info['id_member'] == $user_info['id'])
  159. {
  160. modify_pm_draft($draft, $recipientList);
  161. // some items to return to the form
  162. $context['draft_saved'] = true;
  163. $context['id_pm_draft'] = $id_pm_draft;
  164. }
  165. // otherwise creating a new PM draft.
  166. else
  167. {
  168. create_pm_draft($draft, $recipientList);
  169. // get the new id
  170. $id_pm_draft = $smcFunc['db_insert_id']('{db_prefix}user_drafts', 'id_draft');
  171. // everything go as expected, if not toss back an error
  172. if (!empty($id_pm_draft))
  173. {
  174. $context['draft_saved'] = true;
  175. $context['id_pm_draft'] = $id_pm_draft;
  176. }
  177. else
  178. $post_errors->addError('draft_not_saved');
  179. }
  180. // if we were called from the autosave function, send something back
  181. if (!empty($id_pm_draft) && isset($_REQUEST['xml']) && !$post_errors->hasError('session_timeout'))
  182. {
  183. loadTemplate('Xml');
  184. $context['sub_template'] = 'xml_draft';
  185. $context['id_draft'] = $id_pm_draft;
  186. $context['draft_saved_on'] = time();
  187. obExit();
  188. }
  189. return;
  190. }
  191. /**
  192. * Reads a draft in from the user_drafts table
  193. * Only loads the draft of a given type 0 for post, 1 for pm draft
  194. * Validates that the draft is the users draft
  195. * Optionally loads the draft in to context or superglobal for loading in to the form
  196. *
  197. * @param int $id_draft - draft to load
  198. * @param int $type - type of draft
  199. * @param bool $check - validate the user
  200. * @param bool $load - load it for use in a form
  201. * @return boolean
  202. */
  203. function loadDraft($id_draft, $type = 0, $check = true, $load = false)
  204. {
  205. global $context, $user_info, $modSettings;
  206. // like purell always clean to be sure
  207. $id_draft = (int) $id_draft;
  208. $type = (int) $type;
  209. // nothing to read, nothing to do
  210. if (empty($id_draft))
  211. return false;
  212. // load in this draft from the DB
  213. $drafts_keep_days = !empty($modSettings['drafts_keep_days']) ? (time() - ($modSettings['drafts_keep_days'] * 86400)) : 0;
  214. $draft_info = load_draft($id_draft, $user_info['id'], $type, $drafts_keep_days, $check);
  215. // Load it up for the templates as well
  216. $recipients = array();
  217. if (!empty($load) && !empty($draft_info))
  218. {
  219. if ($type === 0)
  220. {
  221. // a standard post draft?
  222. $context['sticky'] = !empty($draft_info['is_sticky']) ? $draft_info['is_sticky'] : '';
  223. $context['locked'] = !empty($draft_info['locked']) ? $draft_info['locked'] : '';
  224. $context['use_smileys'] = !empty($draft_info['smileys_enabled']) ? true : false;
  225. $context['icon'] = !empty($draft_info['icon']) ? $draft_info['icon'] : 'xx';
  226. $context['message'] = !empty($draft_info['body']) ? $draft_info['body'] : '';
  227. $context['subject'] = !empty($draft_info['subject']) ? $draft_info['subject'] : '';
  228. $context['board'] = !empty($draft_info['board_id']) ? $draft_info['id_board'] : '';
  229. $context['id_draft'] = !empty($draft_info['id_draft']) ? $draft_info['id_draft'] : 0;
  230. }
  231. elseif ($type === 1)
  232. {
  233. // one of those pm drafts? then set it up like we have an error
  234. $_REQUEST['outbox'] = !empty($draft_info['outbox']);
  235. $_REQUEST['subject'] = !empty($draft_info['subject']) ? $draft_info['subject'] : '';
  236. $_REQUEST['message'] = !empty($draft_info['body']) ? $draft_info['body'] : '';
  237. $_REQUEST['replied_to'] = !empty($draft_info['id_reply']) ? $draft_info['id_reply'] : 0;
  238. $context['id_pm_draft'] = !empty($draft_info['id_draft']) ? $draft_info['id_draft'] : 0;
  239. $recipients = unserialize($draft_info['to_list']);
  240. // make sure we only have integers in this array
  241. $recipients['to'] = array_map('intval', $recipients['to']);
  242. $recipients['bcc'] = array_map('intval', $recipients['bcc']);
  243. // pretend we messed up to populate the pm message form
  244. messagePostError(array(), $recipients);
  245. return true;
  246. }
  247. }
  248. return $draft_info;
  249. }
  250. /**
  251. * Loads in a group of drafts for the user of a given type
  252. * (0/posts, 1/pm's)
  253. * loads a specific draft for forum use if selected.
  254. * Used in the posting screens to allow draft selection
  255. * Will load a draft if selected is supplied via post
  256. *
  257. * @param int $member_id
  258. * @param int $topic
  259. * @param int $draft_type
  260. * @return boolean
  261. */
  262. function action_showDrafts($member_id, $topic = false, $draft_type = 0)
  263. {
  264. global $scripturl, $context, $txt, $modSettings;
  265. $context['drafts'] = array();
  266. // Permissions
  267. if (($draft_type === 0 && empty($context['drafts_save'])) || ($draft_type === 1 && empty($context['drafts_pm_save'])) || empty($member_id))
  268. return false;
  269. // has a specific draft has been selected? Load it up if there is not already a message already in the editor
  270. if (isset($_REQUEST['id_draft']) && empty($_POST['subject']) && empty($_POST['message']))
  271. loadDraft((int) $_REQUEST['id_draft'], $draft_type, true, true);
  272. // load all the drafts for this user that meet the criteria
  273. $drafts_keep_days = !empty($modSettings['drafts_keep_days']) ? (time() - ($modSettings['drafts_keep_days'] * 86400)) : 0;
  274. $user_drafts = load_user_drafts($member_id, $topic, $draft_type, $drafts_keep_days);
  275. // add them to the context draft array for template display
  276. foreach ($user_drafts as $draft)
  277. {
  278. // Post drafts
  279. if ($draft_type === 0)
  280. $context['drafts'][] = array(
  281. 'subject' => empty($draft['subject']) ? $txt['drafts_none'] : censorText(shorten_subject(stripslashes($draft['subject']), 24)),
  282. 'poster_time' => timeformat($draft['poster_time']),
  283. 'link' => '<a href="' . $scripturl . '?action=post;board=' . $draft['id_board'] . ';' . (!empty($draft['id_topic']) ? 'topic='. $draft['id_topic'] .'.0;' : '') . 'id_draft=' . $draft['id_draft'] . '">' . (!empty($draft['subject']) ? $draft['subject'] : $txt['drafts_none']) . '</a>',
  284. );
  285. // PM drafts
  286. elseif ($draft_type === 1)
  287. $context['drafts'][] = array(
  288. 'subject' => empty($draft['subject']) ? $txt['drafts_none'] : censorText(shorten_subject(stripslashes($draft['subject']), 24)),
  289. 'poster_time' => timeformat($draft['poster_time']),
  290. 'link' => '<a href="' . $scripturl . '?action=pm;sa=send;id_draft=' . $draft['id_draft'] . '">' . (!empty($draft['subject']) ? $draft['subject'] : $txt['drafts_none']) . '</a>',
  291. );
  292. }
  293. }
  294. /**
  295. * Show all drafts of a given type by the current user
  296. * Uses the showdraft template
  297. * Allows for the deleting and loading/editing of drafts
  298. *
  299. * @param int $memID
  300. * @param int $draft_type = 0
  301. */
  302. function action_showProfileDrafts($memID, $draft_type = 0)
  303. {
  304. global $txt, $scripturl, $modSettings, $context, $smcFunc;
  305. // Some initial context.
  306. $context['start'] = isset($_REQUEST['start']) ? (int) $_REQUEST['start'] : 0;
  307. $context['current_member'] = $memID;
  308. // If just deleting a draft, do it and then redirect back.
  309. if (!empty($_REQUEST['delete']))
  310. {
  311. checkSession('get');
  312. $id_delete = (int) $_REQUEST['delete'];
  313. deleteDrafts($id_delete, $memID);
  314. redirectexit('action=profile;u=' . $memID . ';area=showdrafts;start=' . $context['start']);
  315. }
  316. // Default to 10.
  317. if (empty($_REQUEST['viewscount']) || !is_numeric($_REQUEST['viewscount']))
  318. $_REQUEST['viewscount'] = 10;
  319. // Get the count of applicable drafts
  320. $msgCount = draftsCount($memID, $draft_type);
  321. $maxIndex = (int) $modSettings['defaultMaxMessages'];
  322. // Make sure the starting place makes sense and construct our friend the page index.
  323. $context['page_index'] = constructPageIndex($scripturl . '?action=profile;u=' . $memID . ';area=showdrafts', $context['start'], $msgCount, $maxIndex);
  324. $context['current_page'] = $context['start'] / $maxIndex;
  325. // Reverse the query if we're past 50% of the pages for better performance.
  326. $start = $context['start'];
  327. $reverse = $start > $msgCount / 2;
  328. if ($reverse)
  329. {
  330. $maxIndex = $msgCount < $context['start'] + $modSettings['defaultMaxMessages'] + 1 && $msgCount > $context['start'] ? $msgCount - $context['start'] : (int) $modSettings['defaultMaxMessages'];
  331. $start = $msgCount < $context['start'] + $modSettings['defaultMaxMessages'] + 1 || $msgCount < $context['start'] + $modSettings['defaultMaxMessages'] ? 0 : $msgCount - $context['start'] - $modSettings['defaultMaxMessages'];
  332. }
  333. // Find this user's drafts
  334. $request = $smcFunc['db_query']('', '
  335. SELECT
  336. b.id_board, b.name AS bname,
  337. ud.id_member, ud.id_draft, ud.body, ud.smileys_enabled, ud.subject, ud.poster_time, ud.icon, ud.id_topic, ud.locked, ud.is_sticky
  338. FROM {db_prefix}user_drafts AS ud
  339. INNER JOIN {db_prefix}boards AS b ON (b.id_board = ud.id_board)
  340. WHERE ud.id_member = {int:current_member}
  341. AND type = {int:draft_type}' . (!empty($modSettings['drafts_keep_days']) ? '
  342. AND poster_time > {int:time}' : '') . '
  343. ORDER BY ud.id_draft ' . ($reverse ? 'ASC' : 'DESC') . '
  344. LIMIT ' . $start . ', ' . $maxIndex,
  345. array(
  346. 'current_member' => $memID,
  347. 'draft_type' => $draft_type,
  348. 'time' => (!empty($modSettings['drafts_keep_days']) ? (time() - ($modSettings['drafts_keep_days'] * 86400)) : 0),
  349. )
  350. );
  351. // Start counting at the number of the first message displayed.
  352. $counter = $reverse ? $context['start'] + $maxIndex + 1 : $context['start'];
  353. $context['posts'] = array();
  354. while ($row = $smcFunc['db_fetch_assoc']($request))
  355. {
  356. // Censor....
  357. if (empty($row['body']))
  358. $row['body'] = '';
  359. $row['subject'] = $smcFunc['htmltrim']($row['subject']);
  360. if (empty($row['subject']))
  361. $row['subject'] = $txt['drafts_none'];
  362. censorText($row['body']);
  363. censorText($row['subject']);
  364. // BBC-ilize the message.
  365. $row['body'] = parse_bbc($row['body'], $row['smileys_enabled'], 'draft' . $row['id_draft']);
  366. // And the array...
  367. $context['drafts'][$counter += $reverse ? -1 : 1] = array(
  368. 'body' => $row['body'],
  369. 'counter' => $counter,
  370. 'alternate' => $counter % 2,
  371. 'board' => array(
  372. 'name' => $row['bname'],
  373. 'id' => $row['id_board'],
  374. ),
  375. 'topic' => array(
  376. 'id' => $row['id_topic'],
  377. 'link' => empty($row['id_topic']) ? $row['subject'] : '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.0">' . $row['subject'] . '</a>',
  378. ),
  379. 'subject' => $row['subject'],
  380. 'time' => timeformat($row['poster_time']),
  381. 'timestamp' => forum_time(true, $row['poster_time']),
  382. 'icon' => $row['icon'],
  383. 'id_draft' => $row['id_draft'],
  384. 'locked' => $row['locked'],
  385. 'sticky' => $row['is_sticky'],
  386. 'age' => floor((time() - $row['poster_time']) / 86400),
  387. 'remaining' => (!empty($modSettings['drafts_keep_days']) ? round($modSettings['drafts_keep_days'] - ((time() - $row['poster_time']) / 86400)) : 0),
  388. );
  389. }
  390. $smcFunc['db_free_result']($request);
  391. // If the drafts were retrieved in reverse order, get them right again.
  392. if ($reverse)
  393. $context['drafts'] = array_reverse($context['drafts'], true);
  394. // Menu tab
  395. $context[$context['profile_menu_name']]['tab_data'] = array(
  396. 'title' => $txt['drafts_show'] . ' - ' . $context['member']['name'],
  397. 'icon' => 'message_sm.png'
  398. );
  399. $context['sub_template'] = 'showDrafts';
  400. }
  401. /**
  402. * Show all PM drafts of the current user
  403. * Uses the showpmdraft template
  404. * Allows for the deleting and loading/editing of PM drafts
  405. *
  406. * @param int $memID = -1
  407. */
  408. function action_showPMDrafts($memID = -1)
  409. {
  410. global $txt, $user_info, $scripturl, $modSettings, $context, $smcFunc;
  411. // set up what we will need
  412. $context['start'] = isset($_REQUEST['start']) ? (int) $_REQUEST['start'] : 0;
  413. // If just deleting a draft, do it and then redirect back.
  414. if (!empty($_REQUEST['delete']))
  415. {
  416. checkSession('get');
  417. $id_delete = (int) $_REQUEST['delete'];
  418. deleteDrafts($id_delete, $memID);
  419. // now redirect back to the list
  420. redirectexit('action=pm;sa=showpmdrafts;start=' . $context['start']);
  421. }
  422. // perhaps a draft was selected for editing? if so pass this off
  423. if (!empty($_REQUEST['id_draft']) && !empty($context['drafts_pm_save']) && $memID == $user_info['id'])
  424. {
  425. checkSession('get');
  426. $id_draft = (int) $_REQUEST['id_draft'];
  427. redirectexit('action=pm;sa=send;id_draft=' . $id_draft);
  428. }
  429. // init
  430. $draft_type = 1;
  431. // Default to 10.
  432. if (empty($_REQUEST['viewscount']) || !is_numeric($_REQUEST['viewscount']))
  433. $_REQUEST['viewscount'] = 10;
  434. // Get the count of applicable drafts
  435. $msgCount = draftsCount($memID, $draft_type);
  436. $maxIndex = (int) $modSettings['defaultMaxMessages'];
  437. // Make sure the starting place makes sense and construct our friend the page index.
  438. $context['page_index'] = constructPageIndex($scripturl . '?action=pm;sa=showpmdrafts', $context['start'], $msgCount, $maxIndex);
  439. $context['current_page'] = $context['start'] / $maxIndex;
  440. // Reverse the query if we're past 50% of the total for better performance.
  441. $start = $context['start'];
  442. $reverse = $start > $msgCount / 2;
  443. if ($reverse)
  444. {
  445. $maxIndex = $msgCount < $context['start'] + $modSettings['defaultMaxMessages'] + 1 && $msgCount > $context['start'] ? $msgCount - $context['start'] : (int) $modSettings['defaultMaxMessages'];
  446. $start = $msgCount < $context['start'] + $modSettings['defaultMaxMessages'] + 1 || $msgCount < $context['start'] + $modSettings['defaultMaxMessages'] ? 0 : $msgCount - $context['start'] - $modSettings['defaultMaxMessages'];
  447. }
  448. // Load in this user's PM drafts
  449. $request = $smcFunc['db_query']('', '
  450. SELECT
  451. ud.id_member, ud.id_draft, ud.body, ud.subject, ud.poster_time, ud.outbox, ud.id_reply, ud.to_list
  452. FROM {db_prefix}user_drafts AS ud
  453. WHERE ud.id_member = {int:current_member}
  454. AND type = {int:draft_type}' . (!empty($modSettings['drafts_keep_days']) ? '
  455. AND poster_time > {int:time}' : '') . '
  456. ORDER BY ud.id_draft ' . ($reverse ? 'ASC' : 'DESC') . '
  457. LIMIT ' . $start . ', ' . $maxIndex,
  458. array(
  459. 'current_member' => $memID,
  460. 'draft_type' => $draft_type,
  461. 'time' => (!empty($modSettings['drafts_keep_days']) ? (time() - ($modSettings['drafts_keep_days'] * 86400)) : 0),
  462. )
  463. );
  464. // Start counting at the number of the first message displayed.
  465. $counter = $reverse ? $context['start'] + $maxIndex + 1 : $context['start'];
  466. $context['posts'] = array();
  467. while ($row = $smcFunc['db_fetch_assoc']($request))
  468. {
  469. // Censor....
  470. if (empty($row['body']))
  471. $row['body'] = '';
  472. $row['subject'] = $smcFunc['htmltrim']($row['subject']);
  473. if (empty($row['subject']))
  474. $row['subject'] = $txt['no_subject'];
  475. censorText($row['body']);
  476. censorText($row['subject']);
  477. // BBC-ilize the message.
  478. $row['body'] = parse_bbc($row['body'], true, 'draft' . $row['id_draft']);
  479. // Have they provided who this will go to?
  480. $recipients = array(
  481. 'to' => array(),
  482. 'bcc' => array(),
  483. );
  484. $recipient_ids = (!empty($row['to_list'])) ? unserialize($row['to_list']) : array();
  485. // @todo ... this is a bit ugly since it runs an extra query for every message, do we want this?
  486. // at least its only for draft PM's and only the user can see them ... so not heavily used .. still
  487. if (!empty($recipient_ids['to']) || !empty($recipient_ids['bcc']))
  488. {
  489. $recipient_ids['to'] = array_map('intval', $recipient_ids['to']);
  490. $recipient_ids['bcc'] = array_map('intval', $recipient_ids['bcc']);
  491. $allRecipients = array_merge($recipient_ids['to'], $recipient_ids['bcc']);
  492. $request_2 = $smcFunc['db_query']('', '
  493. SELECT id_member, real_name
  494. FROM {db_prefix}members
  495. WHERE id_member IN ({array_int:member_list})',
  496. array(
  497. 'member_list' => $allRecipients,
  498. )
  499. );
  500. while ($result = $smcFunc['db_fetch_assoc']($request_2))
  501. {
  502. $recipientType = in_array($result['id_member'], $recipient_ids['bcc']) ? 'bcc' : 'to';
  503. $recipients[$recipientType][] = $result['real_name'];
  504. }
  505. $smcFunc['db_free_result']($request_2);
  506. }
  507. // Add the items to the array for template use
  508. $context['drafts'][$counter += $reverse ? -1 : 1] = array(
  509. 'body' => $row['body'],
  510. 'counter' => $counter,
  511. 'alternate' => $counter % 2,
  512. 'subject' => $row['subject'],
  513. 'time' => timeformat($row['poster_time']),
  514. 'timestamp' => forum_time(true, $row['poster_time']),
  515. 'id_draft' => $row['id_draft'],
  516. 'recipients' => $recipients,
  517. 'age' => floor((time() - $row['poster_time']) / 86400),
  518. 'remaining' => (!empty($modSettings['drafts_keep_days']) ? floor($modSettings['drafts_keep_days'] - ((time() - $row['poster_time']) / 86400)) : 0),
  519. );
  520. }
  521. $smcFunc['db_free_result']($request);
  522. // if the drafts were retrieved in reverse order, then put them in the right order again.
  523. if ($reverse)
  524. $context['drafts'] = array_reverse($context['drafts'], true);
  525. // off to the template we go
  526. $context['page_title'] = $txt['drafts'];
  527. $context['sub_template'] = 'showPMDrafts';
  528. $context['linktree'][] = array(
  529. 'url' => $scripturl . '?action=pm;sa=showpmdrafts',
  530. 'name' => $txt['drafts'],
  531. );
  532. }