Yoshi2889 /
SMF2.1
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | /** |
||
| 4 | * This file contains all the functions that allow for the saving, |
||
| 5 | * retrieving, deleting and settings for the drafts function. |
||
| 6 | * |
||
| 7 | * Simple Machines Forum (SMF) |
||
| 8 | * |
||
| 9 | * @package SMF |
||
| 10 | * @author Simple Machines http://www.simplemachines.org |
||
| 11 | * @copyright 2017 Simple Machines and individual contributors |
||
| 12 | * @license http://www.simplemachines.org/about/smf/license.php BSD |
||
| 13 | * |
||
| 14 | * @version 2.1 Beta 4 |
||
| 15 | */ |
||
| 16 | |||
| 17 | if (!defined('SMF')) |
||
| 18 | die('No direct access...'); |
||
| 19 | |||
| 20 | loadLanguage('Drafts'); |
||
| 21 | |||
| 22 | /** |
||
| 23 | * Saves a post draft in the user_drafts table |
||
| 24 | * The core draft feature must be enabled, as well as the post draft option |
||
| 25 | * Determines if this is a new or an existing draft |
||
| 26 | * Returns errors in $post_errors for display in the template |
||
| 27 | * |
||
| 28 | * @param string[] $post_errors Any errors encountered trying to save this draft |
||
| 29 | * @return boolean Always returns true |
||
| 30 | */ |
||
| 31 | function SaveDraft(&$post_errors) |
||
| 32 | { |
||
| 33 | global $context, $user_info, $smcFunc, $modSettings, $board; |
||
| 34 | |||
| 35 | // can you be, should you be ... here? |
||
| 36 | if (empty($modSettings['drafts_post_enabled']) || !allowedTo('post_draft') || !isset($_POST['save_draft']) || !isset($_POST['id_draft'])) |
||
| 37 | return false; |
||
| 38 | |||
| 39 | // read in what they sent us, if anything |
||
| 40 | $id_draft = (int) $_POST['id_draft']; |
||
| 41 | $draft_info = ReadDraft($id_draft); |
||
| 42 | |||
| 43 | // A draft has been saved less than 5 seconds ago, let's not do the autosave again |
||
| 44 | View Code Duplication | if (isset($_REQUEST['xml']) && !empty($draft_info['poster_time']) && time() < $draft_info['poster_time'] + 5) |
|
| 45 | { |
||
| 46 | $context['draft_saved_on'] = $draft_info['poster_time']; |
||
| 47 | |||
| 48 | // since we were called from the autosave function, send something back |
||
| 49 | if (!empty($id_draft)) |
||
| 50 | XmlDraft($id_draft); |
||
| 51 | |||
| 52 | return true; |
||
| 53 | } |
||
| 54 | |||
| 55 | if (!isset($_POST['message'])) |
||
| 56 | $_POST['message'] = isset($_POST['quickReply']) ? $_POST['quickReply'] : ''; |
||
| 57 | |||
| 58 | // prepare any data from the form |
||
| 59 | $topic_id = empty($_REQUEST['topic']) ? 0 : (int) $_REQUEST['topic']; |
||
| 60 | $draft['icon'] = empty($_POST['icon']) ? 'xx' : preg_replace('~[\./\\\\*:"\'<>]~', '', $_POST['icon']); |
||
| 61 | $draft['smileys_enabled'] = isset($_POST['ns']) ? (int) $_POST['ns'] : 0; |
||
| 62 | $draft['locked'] = isset($_POST['lock']) ? (int) $_POST['lock'] : 0; |
||
| 63 | $draft['sticky'] = isset($_POST['sticky']) ? (int) $_POST['sticky'] : 0; |
||
| 64 | $draft['subject'] = strtr($smcFunc['htmlspecialchars']($_POST['subject']), array("\r" => '', "\n" => '', "\t" => '')); |
||
| 65 | $draft['body'] = $smcFunc['htmlspecialchars']($_POST['message'], ENT_QUOTES); |
||
| 66 | |||
| 67 | // message and subject still need a bit more work |
||
| 68 | preparsecode($draft['body']); |
||
| 69 | View Code Duplication | if ($smcFunc['strlen']($draft['subject']) > 100) |
|
| 70 | $draft['subject'] = $smcFunc['substr']($draft['subject'], 0, 100); |
||
| 71 | |||
| 72 | // Modifying an existing draft, like hitting the save draft button or autosave enabled? |
||
| 73 | if (!empty($id_draft) && !empty($draft_info)) |
||
| 74 | { |
||
| 75 | $smcFunc['db_query']('', ' |
||
| 76 | UPDATE {db_prefix}user_drafts |
||
| 77 | SET |
||
| 78 | id_topic = {int:id_topic}, |
||
| 79 | id_board = {int:id_board}, |
||
| 80 | poster_time = {int:poster_time}, |
||
| 81 | subject = {string:subject}, |
||
| 82 | smileys_enabled = {int:smileys_enabled}, |
||
| 83 | body = {string:body}, |
||
| 84 | icon = {string:icon}, |
||
| 85 | locked = {int:locked}, |
||
| 86 | is_sticky = {int:is_sticky} |
||
| 87 | WHERE id_draft = {int:id_draft}', |
||
| 88 | array( |
||
| 89 | 'id_topic' => $topic_id, |
||
| 90 | 'id_board' => $board, |
||
| 91 | 'poster_time' => time(), |
||
| 92 | 'subject' => $draft['subject'], |
||
| 93 | 'smileys_enabled' => (int) $draft['smileys_enabled'], |
||
| 94 | 'body' => $draft['body'], |
||
| 95 | 'icon' => $draft['icon'], |
||
| 96 | 'locked' => $draft['locked'], |
||
| 97 | 'is_sticky' => $draft['sticky'], |
||
| 98 | 'id_draft' => $id_draft, |
||
| 99 | ) |
||
| 100 | ); |
||
| 101 | |||
| 102 | // some items to return to the form |
||
| 103 | $context['draft_saved'] = true; |
||
| 104 | $context['id_draft'] = $id_draft; |
||
| 105 | |||
| 106 | // cleanup |
||
| 107 | unset($_POST['save_draft']); |
||
| 108 | } |
||
| 109 | // otherwise creating a new draft |
||
| 110 | else |
||
| 111 | { |
||
| 112 | $id_draft = $smcFunc['db_insert']('', |
||
| 113 | '{db_prefix}user_drafts', |
||
| 114 | array( |
||
| 115 | 'id_topic' => 'int', |
||
| 116 | 'id_board' => 'int', |
||
| 117 | 'type' => 'int', |
||
| 118 | 'poster_time' => 'int', |
||
| 119 | 'id_member' => 'int', |
||
| 120 | 'subject' => 'string-255', |
||
| 121 | 'smileys_enabled' => 'int', |
||
| 122 | 'body' => (!empty($modSettings['max_messageLength']) && $modSettings['max_messageLength'] > 65534 ? 'string-' . $modSettings['max_messageLength'] : 'string-65534'), |
||
| 123 | 'icon' => 'string-16', |
||
| 124 | 'locked' => 'int', |
||
| 125 | 'is_sticky' => 'int' |
||
| 126 | ), |
||
| 127 | array( |
||
| 128 | $topic_id, |
||
| 129 | $board, |
||
| 130 | 0, |
||
| 131 | time(), |
||
| 132 | $user_info['id'], |
||
| 133 | $draft['subject'], |
||
| 134 | $draft['smileys_enabled'], |
||
| 135 | $draft['body'], |
||
| 136 | $draft['icon'], |
||
| 137 | $draft['locked'], |
||
| 138 | $draft['sticky'] |
||
| 139 | ), |
||
| 140 | array( |
||
| 141 | 'id_draft' |
||
| 142 | ), |
||
| 143 | 1 |
||
| 144 | ); |
||
| 145 | |||
| 146 | // everything go as expected? |
||
| 147 | View Code Duplication | if (!empty($id_draft)) |
|
| 148 | { |
||
| 149 | $context['draft_saved'] = true; |
||
| 150 | $context['id_draft'] = $id_draft; |
||
| 151 | } |
||
| 152 | else |
||
| 153 | $post_errors[] = 'draft_not_saved'; |
||
| 154 | |||
| 155 | // cleanup |
||
| 156 | unset($_POST['save_draft']); |
||
| 157 | } |
||
| 158 | |||
| 159 | // if we were called from the autosave function, send something back |
||
| 160 | View Code Duplication | if (!empty($id_draft) && isset($_REQUEST['xml']) && (!in_array('session_timeout', $post_errors))) |
|
| 161 | { |
||
| 162 | $context['draft_saved_on'] = time(); |
||
| 163 | XmlDraft($id_draft); |
||
| 164 | } |
||
| 165 | |||
| 166 | return true; |
||
| 167 | } |
||
| 168 | |||
| 169 | /** |
||
| 170 | * Saves a PM draft in the user_drafts table |
||
| 171 | * The core draft feature must be enabled, as well as the pm draft option |
||
| 172 | * Determines if this is a new or and update to an existing pm draft |
||
| 173 | * |
||
| 174 | * @param string $post_errors A string of info about errors encountered trying to save this draft |
||
| 175 | * @param array $recipientList An array of data about who this PM is being sent to |
||
| 176 | * @return boolean false if you can't save the draft, true if we're doing this via XML more than 5 seconds after the last save, nothing otherwise |
||
| 177 | */ |
||
| 178 | function SavePMDraft(&$post_errors, $recipientList) |
||
| 179 | { |
||
| 180 | global $context, $user_info, $smcFunc, $modSettings; |
||
| 181 | |||
| 182 | // PM survey says ... can you stay or must you go |
||
| 183 | if (empty($modSettings['drafts_pm_enabled']) || !allowedTo('pm_draft') || !isset($_POST['save_draft'])) |
||
| 184 | return false; |
||
| 185 | |||
| 186 | // read in what you sent us |
||
| 187 | $id_pm_draft = (int) $_POST['id_pm_draft']; |
||
| 188 | $draft_info = ReadDraft($id_pm_draft, 1); |
||
| 189 | |||
| 190 | // 5 seconds is the same limit we have for posting |
||
| 191 | View Code Duplication | if (isset($_REQUEST['xml']) && !empty($draft_info['poster_time']) && time() < $draft_info['poster_time'] + 5) |
|
| 192 | { |
||
| 193 | $context['draft_saved_on'] = $draft_info['poster_time']; |
||
| 194 | |||
| 195 | // Send something back to the javascript caller |
||
| 196 | if (!empty($id_draft)) |
||
|
0 ignored issues
–
show
|
|||
| 197 | XmlDraft($id_draft); |
||
| 198 | |||
| 199 | return true; |
||
| 200 | } |
||
| 201 | |||
| 202 | // determine who this is being sent to |
||
| 203 | if (isset($_REQUEST['xml'])) |
||
| 204 | { |
||
| 205 | $recipientList['to'] = isset($_POST['recipient_to']) ? explode(',', $_POST['recipient_to']) : array(); |
||
| 206 | $recipientList['bcc'] = isset($_POST['recipient_bcc']) ? explode(',', $_POST['recipient_bcc']) : array(); |
||
| 207 | } |
||
| 208 | elseif (!empty($draft_info['to_list']) && empty($recipientList)) |
||
| 209 | $recipientList = $smcFunc['json_decode']($draft_info['to_list'], true); |
||
| 210 | |||
| 211 | // prepare the data we got from the form |
||
| 212 | $reply_id = empty($_POST['replied_to']) ? 0 : (int) $_POST['replied_to']; |
||
| 213 | $draft['body'] = $smcFunc['htmlspecialchars']($_POST['message'], ENT_QUOTES); |
||
| 214 | $draft['subject'] = strtr($smcFunc['htmlspecialchars']($_POST['subject']), array("\r" => '', "\n" => '', "\t" => '')); |
||
| 215 | |||
| 216 | // message and subject always need a bit more work |
||
| 217 | preparsecode($draft['body']); |
||
| 218 | View Code Duplication | if ($smcFunc['strlen']($draft['subject']) > 100) |
|
| 219 | $draft['subject'] = $smcFunc['substr']($draft['subject'], 0, 100); |
||
| 220 | |||
| 221 | // Modifying an existing PM draft? |
||
| 222 | if (!empty($id_pm_draft) && !empty($draft_info)) |
||
| 223 | { |
||
| 224 | $smcFunc['db_query']('', ' |
||
| 225 | UPDATE {db_prefix}user_drafts |
||
| 226 | SET id_reply = {int:id_reply}, |
||
| 227 | type = {int:type}, |
||
| 228 | poster_time = {int:poster_time}, |
||
| 229 | subject = {string:subject}, |
||
| 230 | body = {string:body}, |
||
| 231 | to_list = {string:to_list} |
||
| 232 | WHERE id_draft = {int:id_pm_draft} |
||
| 233 | LIMIT 1', |
||
| 234 | array( |
||
| 235 | 'id_reply' => $reply_id, |
||
| 236 | 'type' => 1, |
||
| 237 | 'poster_time' => time(), |
||
| 238 | 'subject' => $draft['subject'], |
||
| 239 | 'body' => $draft['body'], |
||
| 240 | 'id_pm_draft' => $id_pm_draft, |
||
| 241 | 'to_list' => $smcFunc['json_encode']($recipientList), |
||
| 242 | ) |
||
| 243 | ); |
||
| 244 | |||
| 245 | // some items to return to the form |
||
| 246 | $context['draft_saved'] = true; |
||
| 247 | $context['id_pm_draft'] = $id_pm_draft; |
||
| 248 | } |
||
| 249 | // otherwise creating a new PM draft. |
||
| 250 | else |
||
| 251 | { |
||
| 252 | $id_pm_draft = $smcFunc['db_insert']('', |
||
| 253 | '{db_prefix}user_drafts', |
||
| 254 | array( |
||
| 255 | 'id_reply' => 'int', |
||
| 256 | 'type' => 'int', |
||
| 257 | 'poster_time' => 'int', |
||
| 258 | 'id_member' => 'int', |
||
| 259 | 'subject' => 'string-255', |
||
| 260 | 'body' => 'string-65534', |
||
| 261 | 'to_list' => 'string-255', |
||
| 262 | ), |
||
| 263 | array( |
||
| 264 | $reply_id, |
||
| 265 | 1, |
||
| 266 | time(), |
||
| 267 | $user_info['id'], |
||
| 268 | $draft['subject'], |
||
| 269 | $draft['body'], |
||
| 270 | $smcFunc['json_encode']($recipientList), |
||
| 271 | ), |
||
| 272 | array( |
||
| 273 | 'id_draft' |
||
| 274 | ), |
||
| 275 | 1 |
||
| 276 | ); |
||
| 277 | |||
| 278 | // everything go as expected, if not toss back an error |
||
| 279 | View Code Duplication | if (!empty($id_pm_draft)) |
|
| 280 | { |
||
| 281 | $context['draft_saved'] = true; |
||
| 282 | $context['id_pm_draft'] = $id_pm_draft; |
||
| 283 | } |
||
| 284 | else |
||
| 285 | $post_errors[] = 'draft_not_saved'; |
||
| 286 | } |
||
| 287 | |||
| 288 | // if we were called from the autosave function, send something back |
||
| 289 | View Code Duplication | if (!empty($id_pm_draft) && isset($_REQUEST['xml']) && !in_array('session_timeout', $post_errors)) |
|
| 290 | { |
||
| 291 | $context['draft_saved_on'] = time(); |
||
| 292 | XmlDraft($id_pm_draft); |
||
| 293 | } |
||
| 294 | |||
| 295 | return; |
||
| 296 | } |
||
| 297 | |||
| 298 | /** |
||
| 299 | * Reads a draft in from the user_drafts table |
||
| 300 | * Validates that the draft is the user''s draft |
||
| 301 | * Optionally loads the draft in to context or superglobal for loading in to the form |
||
| 302 | * |
||
| 303 | * @param int $id_draft ID of the draft to load |
||
| 304 | * @param int $type Type of draft - 0 for post or 1 for PM |
||
| 305 | * @param boolean $check Validate that this draft belongs to the current user |
||
| 306 | * @param boolean $load Whether or not to load the data into variables for use on a form |
||
| 307 | * @return boolean|array False if the data couldn't be loaded, true if it's a PM draft or an array of info about the draft if it's a post draft |
||
| 308 | */ |
||
| 309 | function ReadDraft($id_draft, $type = 0, $check = true, $load = false) |
||
| 310 | { |
||
| 311 | global $context, $user_info, $smcFunc, $modSettings; |
||
| 312 | |||
| 313 | // like purell always clean to be sure |
||
| 314 | $id_draft = (int) $id_draft; |
||
| 315 | $type = (int) $type; |
||
| 316 | |||
| 317 | // nothing to read, nothing to do |
||
| 318 | if (empty($id_draft)) |
||
| 319 | return false; |
||
| 320 | |||
| 321 | // load in this draft from the DB |
||
| 322 | $request = $smcFunc['db_query']('', ' |
||
| 323 | SELECT is_sticky, locked, smileys_enabled, icon, body , subject, |
||
| 324 | id_board, id_draft, id_reply, to_list |
||
| 325 | FROM {db_prefix}user_drafts |
||
| 326 | WHERE id_draft = {int:id_draft}' . ($check ? ' |
||
| 327 | AND id_member = {int:id_member}' : '') . ' |
||
| 328 | AND type = {int:type}' . (!empty($modSettings['drafts_keep_days']) ? ' |
||
| 329 | AND poster_time > {int:time}' : '') . ' |
||
| 330 | LIMIT 1', |
||
| 331 | array( |
||
| 332 | 'id_member' => $user_info['id'], |
||
| 333 | 'id_draft' => $id_draft, |
||
| 334 | 'type' => $type, |
||
| 335 | 'time' => (!empty($modSettings['drafts_keep_days']) ? (time() - ($modSettings['drafts_keep_days'] * 86400)) : 0), |
||
| 336 | ) |
||
| 337 | ); |
||
| 338 | |||
| 339 | // no results? |
||
| 340 | if (!$smcFunc['db_num_rows']($request)) |
||
| 341 | return false; |
||
| 342 | |||
| 343 | // load up the data |
||
| 344 | $draft_info = $smcFunc['db_fetch_assoc']($request); |
||
| 345 | $smcFunc['db_free_result']($request); |
||
| 346 | |||
| 347 | // Load it up for the templates as well |
||
| 348 | if (!empty($load)) |
||
| 349 | { |
||
| 350 | if ($type === 0) |
||
| 351 | { |
||
| 352 | // a standard post draft? |
||
| 353 | $context['sticky'] = !empty($draft_info['is_sticky']) ? $draft_info['is_sticky'] : ''; |
||
| 354 | $context['locked'] = !empty($draft_info['locked']) ? $draft_info['locked'] : ''; |
||
| 355 | $context['use_smileys'] = !empty($draft_info['smileys_enabled']) ? true : false; |
||
| 356 | $context['icon'] = !empty($draft_info['icon']) ? $draft_info['icon'] : 'xx'; |
||
| 357 | $context['message'] = !empty($draft_info['body']) ? str_replace('<br>', "\n", un_htmlspecialchars(stripslashes($draft_info['body']))) : ''; |
||
| 358 | $context['subject'] = !empty($draft_info['subject']) ? stripslashes($draft_info['subject']) : ''; |
||
| 359 | $context['board'] = !empty($draft_info['id_board']) ? $draft_info['id_board'] : ''; |
||
| 360 | $context['id_draft'] = !empty($draft_info['id_draft']) ? $draft_info['id_draft'] : 0; |
||
| 361 | } |
||
| 362 | elseif ($type === 1) |
||
| 363 | { |
||
| 364 | // one of those pm drafts? then set it up like we have an error |
||
| 365 | $_REQUEST['subject'] = !empty($draft_info['subject']) ? stripslashes($draft_info['subject']) : ''; |
||
| 366 | $_REQUEST['message'] = !empty($draft_info['body']) ? str_replace('<br>', "\n", un_htmlspecialchars(stripslashes($draft_info['body']))) : ''; |
||
| 367 | $_REQUEST['replied_to'] = !empty($draft_info['id_reply']) ? $draft_info['id_reply'] : 0; |
||
| 368 | $context['id_pm_draft'] = !empty($draft_info['id_draft']) ? $draft_info['id_draft'] : 0; |
||
| 369 | $recipients = $smcFunc['json_decode']($draft_info['to_list'], true); |
||
| 370 | |||
| 371 | // make sure we only have integers in this array |
||
| 372 | $recipients['to'] = array_map('intval', $recipients['to']); |
||
| 373 | $recipients['bcc'] = array_map('intval', $recipients['bcc']); |
||
| 374 | |||
| 375 | // pretend we messed up to populate the pm message form |
||
| 376 | messagePostError(array(), array(), $recipients); |
||
| 377 | return true; |
||
| 378 | } |
||
| 379 | } |
||
| 380 | |||
| 381 | return $draft_info; |
||
| 382 | } |
||
| 383 | |||
| 384 | /** |
||
| 385 | * Deletes one or many drafts from the DB |
||
| 386 | * Validates the drafts are from the user |
||
| 387 | * is supplied an array of drafts will attempt to remove all of them |
||
| 388 | * |
||
| 389 | * @param int $id_draft The ID of the draft to delete |
||
| 390 | * @param boolean $check Whether or not to check that the draft belongs to the current user |
||
| 391 | * @return boolean False if it couldn't be deleted (doesn't return anything otherwise) |
||
| 392 | */ |
||
| 393 | function DeleteDraft($id_draft, $check = true) |
||
| 394 | { |
||
| 395 | global $user_info, $smcFunc; |
||
| 396 | |||
| 397 | // Only a single draft. |
||
| 398 | if (is_numeric($id_draft)) |
||
| 399 | $id_draft = array($id_draft); |
||
| 400 | |||
| 401 | // can't delete nothing |
||
| 402 | if (empty($id_draft) || ($check && empty($user_info['id']))) |
||
| 403 | return false; |
||
| 404 | |||
| 405 | $smcFunc['db_query']('', ' |
||
| 406 | DELETE FROM {db_prefix}user_drafts |
||
| 407 | WHERE id_draft IN ({array_int:id_draft})' . ($check ? ' |
||
| 408 | AND id_member = {int:id_member}' : ''), |
||
| 409 | array( |
||
| 410 | 'id_draft' => $id_draft, |
||
| 411 | 'id_member' => empty($user_info['id']) ? -1 : $user_info['id'], |
||
| 412 | ) |
||
| 413 | ); |
||
| 414 | } |
||
| 415 | |||
| 416 | /** |
||
| 417 | * Loads in a group of drafts for the user of a given type (0/posts, 1/pm's) |
||
| 418 | * loads a specific draft for forum use if selected. |
||
| 419 | * Used in the posting screens to allow draft selection |
||
| 420 | * Will load a draft if selected is supplied via post |
||
| 421 | * |
||
| 422 | * @param int $member_id ID of the member to show drafts for |
||
| 423 | * @param boolean|integer If $type is 1, this can be set to only load drafts for posts in the specific topic |
||
| 424 | * @param int $draft_type The type of drafts to show - 0 for post drafts, 1 for PM drafts |
||
| 425 | * @return boolean False if the drafts couldn't be loaded, nothing otherwise |
||
| 426 | */ |
||
| 427 | function ShowDrafts($member_id, $topic = false, $draft_type = 0) |
||
| 428 | { |
||
| 429 | global $smcFunc, $scripturl, $context, $txt, $modSettings; |
||
| 430 | |||
| 431 | // Permissions |
||
| 432 | if (($draft_type === 0 && empty($context['drafts_save'])) || ($draft_type === 1 && empty($context['drafts_pm_save'])) || empty($member_id)) |
||
| 433 | return false; |
||
| 434 | |||
| 435 | $context['drafts'] = array(); |
||
| 436 | |||
| 437 | // has a specific draft has been selected? Load it up if there is not a message already in the editor |
||
| 438 | if (isset($_REQUEST['id_draft']) && empty($_POST['subject']) && empty($_POST['message'])) |
||
| 439 | ReadDraft((int) $_REQUEST['id_draft'], $draft_type, true, true); |
||
| 440 | |||
| 441 | // load the drafts this user has available |
||
| 442 | $request = $smcFunc['db_query']('', ' |
||
| 443 | SELECT subject, poster_time, id_board, id_topic, id_draft |
||
| 444 | FROM {db_prefix}user_drafts |
||
| 445 | WHERE id_member = {int:id_member}' . ((!empty($topic) && empty($draft_type)) ? ' |
||
| 446 | AND id_topic = {int:id_topic}' : (!empty($topic) ? ' |
||
| 447 | AND id_reply = {int:id_topic}' : '')) . ' |
||
| 448 | AND type = {int:draft_type}' . (!empty($modSettings['drafts_keep_days']) ? ' |
||
| 449 | AND poster_time > {int:time}' : '') . ' |
||
| 450 | ORDER BY poster_time DESC', |
||
| 451 | array( |
||
| 452 | 'id_member' => $member_id, |
||
| 453 | 'id_topic' => (int) $topic, |
||
| 454 | 'draft_type' => $draft_type, |
||
| 455 | 'time' => (!empty($modSettings['drafts_keep_days']) ? (time() - ($modSettings['drafts_keep_days'] * 86400)) : 0), |
||
| 456 | ) |
||
| 457 | ); |
||
| 458 | |||
| 459 | // add them to the draft array for display |
||
| 460 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 461 | { |
||
| 462 | if (empty($row['subject'])) |
||
| 463 | $row['subject'] = $txt['no_subject']; |
||
| 464 | |||
| 465 | // Post drafts |
||
| 466 | if ($draft_type === 0) |
||
| 467 | { |
||
| 468 | $tmp_subject = shorten_subject(stripslashes($row['subject']), 24); |
||
| 469 | $context['drafts'][] = array( |
||
| 470 | 'subject' => censorText($tmp_subject), |
||
| 471 | 'poster_time' => timeformat($row['poster_time']), |
||
| 472 | 'link' => '<a href="' . $scripturl . '?action=post;board=' . $row['id_board'] . ';' . (!empty($row['id_topic']) ? 'topic=' . $row['id_topic'] . '.0;' : '') . 'id_draft=' . $row['id_draft'] . '">' . $row['subject'] . '</a>', |
||
| 473 | ); |
||
| 474 | } |
||
| 475 | // PM drafts |
||
| 476 | elseif ($draft_type === 1) |
||
| 477 | { |
||
| 478 | $tmp_subject = shorten_subject(stripslashes($row['subject']), 24); |
||
| 479 | $context['drafts'][] = array( |
||
| 480 | 'subject' => censorText($tmp_subject), |
||
| 481 | 'poster_time' => timeformat($row['poster_time']), |
||
| 482 | 'link' => '<a href="' . $scripturl . '?action=pm;sa=send;id_draft=' . $row['id_draft'] . '">' . (!empty($row['subject']) ? $row['subject'] : $txt['drafts_none']) . '</a>', |
||
| 483 | ); |
||
| 484 | } |
||
| 485 | } |
||
| 486 | $smcFunc['db_free_result']($request); |
||
| 487 | } |
||
| 488 | |||
| 489 | /** |
||
| 490 | * Returns an xml response to an autosave ajax request |
||
| 491 | * provides the id of the draft saved and the time it was saved |
||
| 492 | * |
||
| 493 | * @param int $id_draft |
||
| 494 | */ |
||
| 495 | function XmlDraft($id_draft) |
||
| 496 | { |
||
| 497 | global $txt, $context; |
||
| 498 | |||
| 499 | header('Content-Type: text/xml; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set'])); |
||
| 500 | |||
| 501 | echo '<?xml version="1.0" encoding="', $context['character_set'], '"?> |
||
| 502 | <drafts> |
||
| 503 | <draft id="', $id_draft, '"><![CDATA[', $txt['draft_saved_on'], ': ', timeformat($context['draft_saved_on']), ']]></draft> |
||
| 504 | </drafts>'; |
||
| 505 | |||
| 506 | obExit(false); |
||
| 507 | } |
||
| 508 | |||
| 509 | /** |
||
| 510 | * Show all drafts of a given type by the current user |
||
| 511 | * Uses the showdraft template |
||
| 512 | * Allows for the deleting and loading/editing of drafts |
||
| 513 | * |
||
| 514 | * @param int $memID |
||
| 515 | * @param int $draft_type |
||
| 516 | */ |
||
| 517 | function showProfileDrafts($memID, $draft_type = 0) |
||
| 518 | { |
||
| 519 | global $txt, $scripturl, $modSettings, $context, $smcFunc, $options; |
||
| 520 | |||
| 521 | // Some initial context. |
||
| 522 | $context['start'] = isset($_REQUEST['start']) ? (int) $_REQUEST['start'] : 0; |
||
| 523 | $context['current_member'] = $memID; |
||
| 524 | |||
| 525 | // If just deleting a draft, do it and then redirect back. |
||
| 526 | if (!empty($_REQUEST['delete'])) |
||
| 527 | { |
||
| 528 | checkSession('get'); |
||
| 529 | $id_delete = (int) $_REQUEST['delete']; |
||
| 530 | |||
| 531 | $smcFunc['db_query']('', ' |
||
| 532 | DELETE FROM {db_prefix}user_drafts |
||
| 533 | WHERE id_draft = {int:id_draft} |
||
| 534 | AND id_member = {int:id_member} |
||
| 535 | AND type = {int:draft_type} |
||
| 536 | LIMIT 1', |
||
| 537 | array( |
||
| 538 | 'id_draft' => $id_delete, |
||
| 539 | 'id_member' => $memID, |
||
| 540 | 'draft_type' => $draft_type, |
||
| 541 | ) |
||
| 542 | ); |
||
| 543 | |||
| 544 | redirectexit('action=profile;u=' . $memID . ';area=showdrafts;start=' . $context['start']); |
||
| 545 | } |
||
| 546 | |||
| 547 | // Default to 10. |
||
| 548 | View Code Duplication | if (empty($_REQUEST['viewscount']) || !is_numeric($_REQUEST['viewscount'])) |
|
| 549 | $_REQUEST['viewscount'] = 10; |
||
| 550 | |||
| 551 | // Get the count of applicable drafts on the boards they can (still) see ... |
||
| 552 | // @todo .. should we just let them see their drafts even if they have lost board access ? |
||
| 553 | $request = $smcFunc['db_query']('', ' |
||
| 554 | SELECT COUNT(id_draft) |
||
| 555 | FROM {db_prefix}user_drafts AS ud |
||
| 556 | INNER JOIN {db_prefix}boards AS b ON (b.id_board = ud.id_board AND {query_see_board}) |
||
| 557 | WHERE id_member = {int:id_member} |
||
| 558 | AND type={int:draft_type}' . (!empty($modSettings['drafts_keep_days']) ? ' |
||
| 559 | AND poster_time > {int:time}' : ''), |
||
| 560 | array( |
||
| 561 | 'id_member' => $memID, |
||
| 562 | 'draft_type' => $draft_type, |
||
| 563 | 'time' => (!empty($modSettings['drafts_keep_days']) ? (time() - ($modSettings['drafts_keep_days'] * 86400)) : 0), |
||
| 564 | ) |
||
| 565 | ); |
||
| 566 | list ($msgCount) = $smcFunc['db_fetch_row']($request); |
||
| 567 | $smcFunc['db_free_result']($request); |
||
| 568 | |||
| 569 | $maxPerPage = empty($modSettings['disableCustomPerPage']) && !empty($options['messages_per_page']) ? $options['messages_per_page'] : $modSettings['defaultMaxMessages']; |
||
| 570 | $maxIndex = $maxPerPage; |
||
| 571 | |||
| 572 | // Make sure the starting place makes sense and construct our friend the page index. |
||
| 573 | $context['page_index'] = constructPageIndex($scripturl . '?action=profile;u=' . $memID . ';area=showdrafts', $context['start'], $msgCount, $maxIndex); |
||
| 574 | $context['current_page'] = $context['start'] / $maxIndex; |
||
| 575 | |||
| 576 | // Reverse the query if we're past 50% of the pages for better performance. |
||
| 577 | $start = $context['start']; |
||
| 578 | $reverse = $_REQUEST['start'] > $msgCount / 2; |
||
| 579 | View Code Duplication | if ($reverse) |
|
| 580 | { |
||
| 581 | $maxIndex = $msgCount < $context['start'] + $maxPerPage + 1 && $msgCount > $context['start'] ? $msgCount - $context['start'] : $maxPerPage; |
||
| 582 | $start = $msgCount < $context['start'] + $maxPerPage + 1 || $msgCount < $context['start'] + $maxPerPage ? 0 : $msgCount - $context['start'] - $maxPerPage; |
||
| 583 | } |
||
| 584 | |||
| 585 | // Find this user's drafts for the boards they can access |
||
| 586 | // @todo ... do we want to do this? If they were able to create a draft, do we remove thier access to said draft if they loose |
||
| 587 | // access to the board or if the topic moves to a board they can not see? |
||
| 588 | $request = $smcFunc['db_query']('', ' |
||
| 589 | SELECT |
||
| 590 | b.id_board, b.name AS bname, |
||
| 591 | 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 |
||
| 592 | FROM {db_prefix}user_drafts AS ud |
||
| 593 | INNER JOIN {db_prefix}boards AS b ON (b.id_board = ud.id_board AND {query_see_board}) |
||
| 594 | WHERE ud.id_member = {int:current_member} |
||
| 595 | AND type = {int:draft_type}' . (!empty($modSettings['drafts_keep_days']) ? ' |
||
| 596 | AND poster_time > {int:time}' : '') . ' |
||
| 597 | ORDER BY ud.id_draft ' . ($reverse ? 'ASC' : 'DESC') . ' |
||
| 598 | LIMIT {int:start}, {int:max}', |
||
| 599 | array( |
||
| 600 | 'current_member' => $memID, |
||
| 601 | 'draft_type' => $draft_type, |
||
| 602 | 'time' => (!empty($modSettings['drafts_keep_days']) ? (time() - ($modSettings['drafts_keep_days'] * 86400)) : 0), |
||
| 603 | 'start' => $start, |
||
| 604 | 'max' => $maxIndex, |
||
| 605 | ) |
||
| 606 | ); |
||
| 607 | |||
| 608 | // Start counting at the number of the first message displayed. |
||
| 609 | $counter = $reverse ? $context['start'] + $maxIndex + 1 : $context['start']; |
||
| 610 | $context['posts'] = array(); |
||
| 611 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 612 | { |
||
| 613 | // Censor.... |
||
| 614 | if (empty($row['body'])) |
||
| 615 | $row['body'] = ''; |
||
| 616 | |||
| 617 | $row['subject'] = $smcFunc['htmltrim']($row['subject']); |
||
| 618 | if (empty($row['subject'])) |
||
| 619 | $row['subject'] = $txt['no_subject']; |
||
| 620 | |||
| 621 | censorText($row['body']); |
||
| 622 | censorText($row['subject']); |
||
| 623 | |||
| 624 | // BBC-ilize the message. |
||
| 625 | $row['body'] = parse_bbc($row['body'], $row['smileys_enabled'], 'draft' . $row['id_draft']); |
||
| 626 | |||
| 627 | // And the array... |
||
| 628 | $context['drafts'][$counter += $reverse ? -1 : 1] = array( |
||
| 629 | 'body' => $row['body'], |
||
| 630 | 'counter' => $counter, |
||
| 631 | 'board' => array( |
||
| 632 | 'name' => $row['bname'], |
||
| 633 | 'id' => $row['id_board'] |
||
| 634 | ), |
||
| 635 | 'topic' => array( |
||
| 636 | 'id' => $row['id_topic'], |
||
| 637 | 'link' => empty($row['id']) ? $row['subject'] : '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.0">' . $row['subject'] . '</a>', |
||
| 638 | ), |
||
| 639 | 'subject' => $row['subject'], |
||
| 640 | 'time' => timeformat($row['poster_time']), |
||
| 641 | 'timestamp' => forum_time(true, $row['poster_time']), |
||
| 642 | 'icon' => $row['icon'], |
||
| 643 | 'id_draft' => $row['id_draft'], |
||
| 644 | 'locked' => $row['locked'], |
||
| 645 | 'sticky' => $row['is_sticky'], |
||
| 646 | ); |
||
| 647 | } |
||
| 648 | $smcFunc['db_free_result']($request); |
||
| 649 | |||
| 650 | // If the drafts were retrieved in reverse order, get them right again. |
||
| 651 | if ($reverse) |
||
| 652 | $context['drafts'] = array_reverse($context['drafts'], true); |
||
| 653 | |||
| 654 | // Menu tab |
||
| 655 | $context[$context['profile_menu_name']]['tab_data'] = array( |
||
| 656 | 'title' => $txt['drafts_show'], |
||
| 657 | 'description' => $txt['drafts_show_desc'], |
||
| 658 | 'icon_class' => 'pm_icons inbox' |
||
| 659 | ); |
||
| 660 | $context['sub_template'] = 'showDrafts'; |
||
| 661 | } |
||
| 662 | |||
| 663 | /** |
||
| 664 | * Show all PM drafts of the current user |
||
| 665 | * Uses the showpmdraft template |
||
| 666 | * Allows for the deleting and loading/editing of drafts |
||
| 667 | * |
||
| 668 | * @param int $memID |
||
| 669 | */ |
||
| 670 | function showPMDrafts($memID = -1) |
||
| 671 | { |
||
| 672 | global $txt, $user_info, $scripturl, $modSettings, $context, $smcFunc, $options; |
||
| 673 | |||
| 674 | // init |
||
| 675 | $draft_type = 1; |
||
| 676 | |||
| 677 | // If just deleting a draft, do it and then redirect back. |
||
| 678 | if (!empty($_REQUEST['delete'])) |
||
| 679 | { |
||
| 680 | checkSession('get'); |
||
| 681 | $id_delete = (int) $_REQUEST['delete']; |
||
| 682 | $start = isset($_REQUEST['start']) ? (int) $_REQUEST['start'] : 0; |
||
| 683 | |||
| 684 | $smcFunc['db_query']('', ' |
||
| 685 | DELETE FROM {db_prefix}user_drafts |
||
| 686 | WHERE id_draft = {int:id_draft} |
||
| 687 | AND id_member = {int:id_member} |
||
| 688 | AND type = {int:draft_type} |
||
| 689 | LIMIT 1', |
||
| 690 | array( |
||
| 691 | 'id_draft' => $id_delete, |
||
| 692 | 'id_member' => $memID, |
||
| 693 | 'draft_type' => $draft_type, |
||
| 694 | ) |
||
| 695 | ); |
||
| 696 | |||
| 697 | // now redirect back to the list |
||
| 698 | redirectexit('action=pm;sa=showpmdrafts;start=' . $start); |
||
| 699 | } |
||
| 700 | |||
| 701 | // perhaps a draft was selected for editing? if so pass this off |
||
| 702 | if (!empty($_REQUEST['id_draft']) && !empty($context['drafts_pm_save']) && $memID == $user_info['id']) |
||
| 703 | { |
||
| 704 | checkSession('get'); |
||
| 705 | $id_draft = (int) $_REQUEST['id_draft']; |
||
| 706 | redirectexit('action=pm;sa=send;id_draft=' . $id_draft); |
||
| 707 | } |
||
| 708 | |||
| 709 | // Default to 10. |
||
| 710 | View Code Duplication | if (empty($_REQUEST['viewscount']) || !is_numeric($_REQUEST['viewscount'])) |
|
| 711 | $_REQUEST['viewscount'] = 10; |
||
| 712 | |||
| 713 | // Get the count of applicable drafts |
||
| 714 | $request = $smcFunc['db_query']('', ' |
||
| 715 | SELECT COUNT(id_draft) |
||
| 716 | FROM {db_prefix}user_drafts |
||
| 717 | WHERE id_member = {int:id_member} |
||
| 718 | AND type={int:draft_type}' . (!empty($modSettings['drafts_keep_days']) ? ' |
||
| 719 | AND poster_time > {int:time}' : ''), |
||
| 720 | array( |
||
| 721 | 'id_member' => $memID, |
||
| 722 | 'draft_type' => $draft_type, |
||
| 723 | 'time' => (!empty($modSettings['drafts_keep_days']) ? (time() - ($modSettings['drafts_keep_days'] * 86400)) : 0), |
||
| 724 | ) |
||
| 725 | ); |
||
| 726 | list ($msgCount) = $smcFunc['db_fetch_row']($request); |
||
| 727 | $smcFunc['db_free_result']($request); |
||
| 728 | |||
| 729 | $maxPerPage = empty($modSettings['disableCustomPerPage']) && !empty($options['messages_per_page']) ? $options['messages_per_page'] : $modSettings['defaultMaxMessages']; |
||
| 730 | $maxIndex = $maxPerPage; |
||
| 731 | |||
| 732 | // Make sure the starting place makes sense and construct our friend the page index. |
||
| 733 | $context['page_index'] = constructPageIndex($scripturl . '?action=pm;sa=showpmdrafts', $context['start'], $msgCount, $maxIndex); |
||
| 734 | $context['current_page'] = $context['start'] / $maxIndex; |
||
| 735 | |||
| 736 | // Reverse the query if we're past 50% of the total for better performance. |
||
| 737 | $start = $context['start']; |
||
| 738 | $reverse = $_REQUEST['start'] > $msgCount / 2; |
||
| 739 | View Code Duplication | if ($reverse) |
|
| 740 | { |
||
| 741 | $maxIndex = $msgCount < $context['start'] + $maxPerPage + 1 && $msgCount > $context['start'] ? $msgCount - $context['start'] : $maxPerPage; |
||
| 742 | $start = $msgCount < $context['start'] + $maxPerPage + 1 || $msgCount < $context['start'] + $maxPerPage ? 0 : $msgCount - $context['start'] - $maxPerPage; |
||
| 743 | } |
||
| 744 | |||
| 745 | // Load in this user's PM drafts |
||
| 746 | $request = $smcFunc['db_query']('', ' |
||
| 747 | SELECT |
||
| 748 | ud.id_member, ud.id_draft, ud.body, ud.subject, ud.poster_time, ud.id_reply, ud.to_list |
||
| 749 | FROM {db_prefix}user_drafts AS ud |
||
| 750 | WHERE ud.id_member = {int:current_member} |
||
| 751 | AND type = {int:draft_type}' . (!empty($modSettings['drafts_keep_days']) ? ' |
||
| 752 | AND poster_time > {int:time}' : '') . ' |
||
| 753 | ORDER BY ud.id_draft ' . ($reverse ? 'ASC' : 'DESC') . ' |
||
| 754 | LIMIT {int:start}, {int:max}', |
||
| 755 | array( |
||
| 756 | 'current_member' => $memID, |
||
| 757 | 'draft_type' => $draft_type, |
||
| 758 | 'time' => (!empty($modSettings['drafts_keep_days']) ? (time() - ($modSettings['drafts_keep_days'] * 86400)) : 0), |
||
| 759 | 'start' => $start, |
||
| 760 | 'max' => $maxIndex, |
||
| 761 | ) |
||
| 762 | ); |
||
| 763 | |||
| 764 | // Start counting at the number of the first message displayed. |
||
| 765 | $counter = $reverse ? $context['start'] + $maxIndex + 1 : $context['start']; |
||
| 766 | $context['posts'] = array(); |
||
| 767 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 768 | { |
||
| 769 | // Censor.... |
||
| 770 | if (empty($row['body'])) |
||
| 771 | $row['body'] = ''; |
||
| 772 | |||
| 773 | $row['subject'] = $smcFunc['htmltrim']($row['subject']); |
||
| 774 | if (empty($row['subject'])) |
||
| 775 | $row['subject'] = $txt['no_subject']; |
||
| 776 | |||
| 777 | censorText($row['body']); |
||
| 778 | censorText($row['subject']); |
||
| 779 | |||
| 780 | // BBC-ilize the message. |
||
| 781 | $row['body'] = parse_bbc($row['body'], true, 'draft' . $row['id_draft']); |
||
| 782 | |||
| 783 | // Have they provide who this will go to? |
||
| 784 | $recipients = array( |
||
| 785 | 'to' => array(), |
||
| 786 | 'bcc' => array(), |
||
| 787 | ); |
||
| 788 | $recipient_ids = (!empty($row['to_list'])) ? $smcFunc['json_decode']($row['to_list'], true) : array(); |
||
| 789 | |||
| 790 | // @todo ... this is a bit ugly since it runs an extra query for every message, do we want this? |
||
| 791 | // at least its only for draft PM's and only the user can see them ... so not heavily used .. still |
||
| 792 | if (!empty($recipient_ids['to']) || !empty($recipient_ids['bcc'])) |
||
| 793 | { |
||
| 794 | $recipient_ids['to'] = array_map('intval', $recipient_ids['to']); |
||
| 795 | $recipient_ids['bcc'] = array_map('intval', $recipient_ids['bcc']); |
||
| 796 | $allRecipients = array_merge($recipient_ids['to'], $recipient_ids['bcc']); |
||
| 797 | |||
| 798 | $request_2 = $smcFunc['db_query']('', ' |
||
| 799 | SELECT id_member, real_name |
||
| 800 | FROM {db_prefix}members |
||
| 801 | WHERE id_member IN ({array_int:member_list})', |
||
| 802 | array( |
||
| 803 | 'member_list' => $allRecipients, |
||
| 804 | ) |
||
| 805 | ); |
||
| 806 | while ($result = $smcFunc['db_fetch_assoc']($request_2)) |
||
| 807 | { |
||
| 808 | $recipientType = in_array($result['id_member'], $recipient_ids['bcc']) ? 'bcc' : 'to'; |
||
| 809 | $recipients[$recipientType][] = $result['real_name']; |
||
| 810 | } |
||
| 811 | $smcFunc['db_free_result']($request_2); |
||
| 812 | } |
||
| 813 | |||
| 814 | // Add the items to the array for template use |
||
| 815 | $context['drafts'][$counter += $reverse ? -1 : 1] = array( |
||
| 816 | 'body' => $row['body'], |
||
| 817 | 'counter' => $counter, |
||
| 818 | 'subject' => $row['subject'], |
||
| 819 | 'time' => timeformat($row['poster_time']), |
||
| 820 | 'timestamp' => forum_time(true, $row['poster_time']), |
||
| 821 | 'id_draft' => $row['id_draft'], |
||
| 822 | 'recipients' => $recipients, |
||
| 823 | 'age' => floor((time() - $row['poster_time']) / 86400), |
||
| 824 | 'remaining' => (!empty($modSettings['drafts_keep_days']) ? floor($modSettings['drafts_keep_days'] - ((time() - $row['poster_time']) / 86400)) : 0), |
||
| 825 | ); |
||
| 826 | } |
||
| 827 | $smcFunc['db_free_result']($request); |
||
| 828 | |||
| 829 | // if the drafts were retrieved in reverse order, then put them in the right order again. |
||
| 830 | if ($reverse) |
||
| 831 | $context['drafts'] = array_reverse($context['drafts'], true); |
||
| 832 | |||
| 833 | // off to the template we go |
||
| 834 | $context['page_title'] = $txt['drafts']; |
||
| 835 | $context['sub_template'] = 'showPMDrafts'; |
||
| 836 | $context['linktree'][] = array( |
||
| 837 | 'url' => $scripturl . '?action=pm;sa=showpmdrafts', |
||
| 838 | 'name' => $txt['drafts'], |
||
| 839 | ); |
||
| 840 | } |
||
| 841 | |||
| 842 | ?> |
This check looks for calls to
isset(...)orempty()on variables that are yet undefined. These calls will always produce the same result and can be removed.This is most likely caused by the renaming of a variable or the removal of a function/method parameter.