function shd_profile_show_tickets($memID) { global $txt, $user_info, $scripturl, $modSettings, $smcFunc, $board, $user_profile, $context; // Navigation $context['show_tickets_navigation'] = array('tickets' => array('text' => 'shd_profile_show_tickets', 'lang' => true, 'url' => $scripturl . '?action=profile;u=' . $memID . ';area=hd_showtickets;sa=tickets'), 'replies' => array('text' => 'shd_profile_show_replies', 'lang' => true, 'url' => $scripturl . '?action=profile;u=' . $memID . ';area=hd_showtickets;sa=replies')); // We might be adding the monitor/ignore lists, but we're only interested in those if we're actually on our own page. if ($memID == $user_info['id']) { if (shd_allowed_to('shd_monitor_ticket_any') || shd_allowed_to('shd_monitor_ticket_own')) { $context['show_tickets_navigation']['monitor'] = array('text' => 'shd_profile_show_monitor', 'lang' => true, 'url' => $scripturl . '?action=profile;u=' . $memID . ';area=hd_showtickets;sa=monitor'); } if (shd_allowed_to('shd_ignore_ticket_any') || shd_allowed_to('shd_ignore_ticket_own')) { $context['show_tickets_navigation']['ignore'] = array('text' => 'shd_profile_show_ignore', 'lang' => true, 'url' => $scripturl . '?action=profile;u=' . $memID . ';area=hd_showtickets;sa=ignore'); } // We have the monitor and ignore lists in this area but this code can't deal with it, so we need to go somewhere else with it. if (isset($_GET['sa']) && ($_GET['sa'] == 'monitor' || $_GET['sa'] == 'ignore')) { return shd_profile_show_notify_override($memID); } } $context['page_title'] = $txt['shd_profile_show_tickets'] . ' - ' . $user_profile[$memID]['real_name']; $context['sub_template'] = 'shd_profile_show_tickets'; $context['start'] = (int) $_REQUEST['start']; // The time has come to choose: Tickets, or just replies? $context['can_haz_replies'] = isset($_GET['sa']) && $_GET['sa'] == 'replies' ? true : false; // The active button. $context['show_tickets_navigation'][$context['can_haz_replies'] ? 'replies' : 'tickets']['active'] = true; // "That still only counts as one!" if ($context['can_haz_replies']) { $request = shd_db_query('', ' SELECT COUNT(hdtr.id_msg) FROM {db_prefix}helpdesk_ticket_replies AS hdtr LEFT JOIN {db_prefix}helpdesk_tickets AS hdt ON(hdtr.id_ticket = hdt.id_ticket) WHERE hdtr.id_member = {int:user} AND {query_see_ticket}', array('user' => $memID)); } else { $request = shd_db_query('', ' SELECT COUNT(hdt.id_ticket) FROM {db_prefix}helpdesk_tickets AS hdt WHERE hdt.id_member_started = {int:user} AND {query_see_ticket}', array('user' => $memID)); } list($item_count) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); // Max? Max? Where are you? $request = shd_db_query('', ' SELECT MIN(hdtr.id_msg), MAX(hdtr.id_msg) FROM {db_prefix}helpdesk_ticket_replies AS hdtr LEFT JOIN {db_prefix}helpdesk_tickets AS hdt ON(hdtr.id_ticket = hdt.id_ticket) WHERE hdtr.id_member = {int:user} AND {query_see_ticket}', array('user' => $memID)); list($min_msg_member, $max_msg_member) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); $reverse = false; $max_index = (int) $modSettings['defaultMaxMessages']; // A little page index to help us along the way! $context['page_index'] = shd_no_expand_pageindex($scripturl . '?action=profile;u=' . $memID . ';area=hd_showtickets' . ($context['can_haz_replies'] ? ';sa=replies' : ''), $context['start'], $item_count, $max_index); $context['current_page'] = $context['start'] / $max_index; // Reverse the query if we're past 50% of the pages for better performance. $start = $context['start']; $reverse = $_REQUEST['start'] > $item_count / 2; if ($reverse) { $max_index = $item_count < $context['start'] + $modSettings['defaultMaxMessages'] + 1 && $item_count > $context['start'] ? $item_count - $context['start'] : (int) $modSettings['defaultMaxMessages']; $start = $item_count < $context['start'] + $modSettings['defaultMaxMessages'] + 1 || $item_count < $context['start'] + $modSettings['defaultMaxMessages'] ? 0 : $item_count - $context['start'] - $modSettings['defaultMaxMessages']; } // Bring 'em to me! $looped = false; while (true) { if ($context['can_haz_replies']) { $request = shd_db_query('', ' SELECT hdtr.id_member, hdt.subject, hdt.id_first_msg, hdtr.body, hdtr.smileys_enabled, hdtr.poster_time, hdtr.id_ticket, hdtr.id_msg FROM {db_prefix}helpdesk_ticket_replies AS hdtr INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdt.id_ticket = hdtr.id_ticket) WHERE hdtr.id_member = {int:user} AND {query_see_ticket} ORDER BY hdtr.id_msg ' . ($reverse ? 'ASC' : 'DESC') . ' LIMIT ' . $start . ', ' . $max_index, array('user' => $memID)); } else { $request = shd_db_query('', ' SELECT hdt.id_member_started, hdt.id_first_msg, hdt.id_last_msg, hdt.subject, hdtr.body, hdtr.smileys_enabled, hdtr.poster_time, hdtr.id_ticket, hdtr.id_msg FROM {db_prefix}helpdesk_tickets AS hdt INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hdtr.id_msg = hdt.id_first_msg) WHERE hdt.id_member_started = {int:user} AND {query_see_ticket} ORDER BY hdt.id_first_msg ' . ($reverse ? 'ASC' : 'DESC') . ' LIMIT ' . $start . ', ' . $max_index, array('user' => $memID)); } // Hold it! if ($smcFunc['db_num_rows']($request) === $max_index || $looped) { break; } $looped = true; } // Start counting at the number of the first message displayed. $counter = $reverse ? $context['start'] + $max_index + 1 : $context['start']; $context['items'] = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { // Censor the content censorText($row['body']); censorText($row['subject']); // Do the parsing dance! Eh... $row['body'] = shd_format_text($row['body'], $row['smileys_enabled'], 'shd_reply_' . $row['id_msg']); // And finally, store the load of cr--... the results! $context['items'][$counter += $reverse ? -1 : 1] = array('body' => $row['body'], 'counter' => $counter, 'alternate' => $counter % 2, 'ticket' => $row['id_ticket'], 'subject' => $row['subject'], 'start' => 'msg' . $row['id_msg'], 'time' => timeformat($row['poster_time']), 'timestamp' => forum_time(true, $row['poster_time']), 'msg' => $row['id_msg'], 'is_ticket' => empty($context['can_haz_replies']) ? true : $row['id_msg'] == $row['id_first_msg']); } // Freedom. $smcFunc['db_free_result']($request); // Head's up, feet's down. if ($reverse) { $context['items'] = array_reverse($context['items'], true); } }
/** * Display the notice of email. * * @todo Finish documenting * @since 2.0 */ function shd_notify_popup() { global $txt, $context, $settings, $modSettings, $smcFunc, $user_profile, $user_info, $scripturl; // First, verify we got a log entry, that the log entry is right, and it points to a ticket we can actually see. $_GET['log'] = isset($_GET['log']) ? (int) $_GET['log'] : 0; $email_type = isset($_GET['template']) ? preg_replace('~[^a-z_]~', '', $_GET['template']) : ''; if (empty($modSettings['shd_display_ticket_logs']) || empty($_GET['log']) || empty($email_type)) { fatal_lang_error('no_access', false); } $query = $smcFunc['db_query']('', ' SELECT hdla.id_member, hdla.id_ticket, hdla.id_msg, hdla.extra, IFNULL(hdtr.body, {string:empty}) AS body, IFNULL(mem.real_name, hdtr.poster_name) AS poster_name FROM {db_prefix}helpdesk_log_action AS hdla LEFT JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hdla.id_msg = hdtr.id_msg) LEFT JOIN {db_prefix}members AS mem ON (hdtr.id_member = mem.id_member) WHERE id_action = {int:log} AND action = {string:notify}', array('log' => $_GET['log'], 'notify' => 'notify', 'empty' => '')); if ($smcFunc['db_num_rows']($query) == 0) { $smcFunc['db_free_result']($query); fatal_lang_error('no_access'); } $row = $smcFunc['db_fetch_assoc']($query); $smcFunc['db_free_result']($query); $row['extra'] = unserialize($row['extra']); // Just check we did actually log an email of that type. if (empty($row['extra']['emails'][$_GET['template']])) { fatal_lang_error('no_access', false); } $ticketinfo = shd_load_ticket($row['id_ticket']); // OK, if we're here, we can see the ticket. Can we actually see the email log at this point? if (!shd_allowed_to('shd_view_ticket_logs_any', $ticketinfo['dept']) && (!shd_allowed_to('shd_view_ticket_logs_own', $ticketinfo['dept']) || !$ticketinfo['is_own'])) { fatal_lang_error('no_access', false); } // We're reusing the Help template, need its language file. loadLanguage('Help'); shd_load_language('sd_language/SimpleDeskAdmin'); shd_load_language('sd_language/SimpleDeskLogAction'); shd_load_language('sd_language/SimpleDeskNotifications'); // Set the page up loadTemplate('Help'); $context['page_title'] = $context['forum_name'] . ' - ' . $txt['shd_log_notifications']; $context['template_layers'] = array(); $context['sub_template'] = 'popup'; $users = array(); // First, get the list of users, and load their username etc if we haven't already attempted it before. if (isset($row['extra']['emails'][$email_type]['u'])) { $users = array_merge($users, explode(',', $row['extra']['emails'][$email_type]['u'])); } if (!empty($users)) { $users = array_unique($users); if (!empty($users)) { loadMemberData($users, false, 'minimal'); } } // Now we have all the usernames for this instance, let's go and build this entry. $context['help_text'] = $txt['shd_log_notify_to'] . '<br />'; $new_content = ''; if (!empty($users)) { $first = true; foreach ($users as $user) { if (empty($user_profile[$user])) { continue; } $new_content .= ($first ? '<img src="' . shd_image_url('user.png') . '" alt="" /> ' : ', ') . shd_profile_link($user_profile[$user]['real_name'], $user); $first = false; } } if (!empty($row['extra']['emails'][$email_type]['e'])) { $emails = explode(',', $row['extra']['emails'][$email_type]['e']); // Admins can see the actual emails. if (shd_allowed_to('admin_helpdesk', 0) || $user_info['is_admin']) { foreach ($emails as $key => $value) { $emails[$key] = '<a href="mailto:' . $value . '">' . $value . '</a>'; } $new_content .= '<img src="' . shd_image_url('log_notify.png') . '" alt="" /> ' . implode(', ', $emails); } else { $new_content .= '<img src="' . shd_image_url('log_notify.png') . '" alt="" /> ' . (count($emails) == 1 ? $txt['shd_log_notify_hiddenemail_1'] : sprintf($txt['shd_log_notify_hiddenemail'], count($emails))); } } if (!empty($new_content)) { $context['help_text'] .= $new_content; } $context['help_text'] .= '<hr />'; // So the general prep is done. Now let's rebuild the email contents. if (empty($row['extra']['withbody']) || empty($row['body'])) { $body = ''; } else { $body = trim(un_htmlspecialchars(strip_tags(strtr(shd_format_text($row['body'], false), array('<br />' => "\n", '</div>' => "\n", '</li>' => "\n", '[' => '[', ']' => ']'))))); } $replacements = array("\n" => '<br />', '{ticket_id}' => str_pad($row['id_ticket'], $modSettings['shd_zerofill'], '0', STR_PAD_LEFT), '{subject}' => empty($row['extra']['subject']) ? $txt['no_subject'] : $row['extra']['subject'], '{ticketlink}' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $row['id_ticket'] . (empty($row['id_msg']) ? '.0' : '.msg' . $row['id_msg'] . '#msg' . $row['id_msg']), '{body}' => $body, '{poster_name}' => $row['poster_name']); $email_subject = str_replace(array_keys($replacements), array_values($replacements), $txt['template_subject_notify_' . $email_type]); $email_body = str_replace(array_keys($replacements), array_values($replacements), $txt['template_' . (empty($row['extra']['withbody']) || empty($row['body']) ? 'body' : 'bodyfull') . '_notify_' . $email_type]); $context['help_text'] .= '<strong>' . $txt['subject'] . ':</strong> ' . $email_subject . '<br /><br />' . $email_body; }
function shd_prepare_reply_context() { global $settings, $txt, $modSettings, $scripturl, $options, $user_info, $smcFunc; global $memberContext, $context, $reply_request; if (empty($reply_request)) { return false; } $message = $smcFunc['db_fetch_assoc']($reply_request); if (!$message) { $smcFunc['db_free_result']($reply_request); return false; } if (!loadMemberContext($message['id_member'], true)) { // Notice this information isn't used anywhere else.... $memberContext[$message['id_member']]['name'] = $message['poster_name']; $memberContext[$message['id_member']]['id'] = 0; $memberContext[$message['id_member']]['group'] = $txt['guest_title']; $memberContext[$message['id_member']]['link'] = $message['poster_name']; $memberContext[$message['id_member']]['email'] = $message['poster_email']; $memberContext[$message['id_member']]['show_email'] = showEmailAddress(true, 0); $memberContext[$message['id_member']]['is_guest'] = true; $memberContext[$message['id_member']]['group_stars'] = ''; } $memberContext[$message['id_member']]['ip'] = $message['poster_ip']; censorText($message['body']); $message['body'] = shd_format_text($message['body'], $message['smileys_enabled'], 'shd_reply_' . $message['id_msg']); $output = array('id' => $message['id_msg'], 'member' => &$memberContext[$message['id_member']], 'time' => timeformat($message['poster_time']), 'timestamp' => forum_time(true, $message['poster_time']), 'body' => $message['body'], 'is_staff' => !empty($context['shd_is_staff'][$message['id_member']]), 'can_edit' => shd_allowed_to('shd_edit_reply_any', $context['ticket_form']['dept']) || $message['id_member'] == $user_info['id'] && shd_allowed_to('shd_edit_reply_own', $context['ticket_form']['dept']), 'ip_address' => $message['poster_ip']); if (!empty($message['modified_time'])) { $output['modified'] = array('time' => timeformat($message['modified_time']), 'timestamp' => forum_time(true, $message['modified_time']), 'id' => !empty($user_profile[$message['modified_member']]) ? $message['modified_member'] : 0, 'name' => !empty($user_profile[$message['modified_member']]) ? $user_profile[$message['modified_member']]['real_name'] : $message['modified_name']); $output['modified']['link'] = shd_profile_link($output['modified']['name'], $output['modified']['id']); } return $output; }
/** * Callback function for the template to load messages. * * The process set up by shd_view_ticket() and invoked within template_view_replies() is reasonably complex. * {@link shd_view_ticket()} identifies what messages should be displayed on the current page of the ticket, and performs a query * to load the ticket data. Instead, however, of retrieving every row directly into memory before passing to the template, * it passes the query result, and the name of a handler function into $context, so the template can call to get an * individual row at a time, which saves memory amongst other things. * * With respect to {@link shd_view_ticket()}, the relevant items are $reply_request being defined and $context['get_replies'] * being defined as the name of this function, and in {@link template_view_replies()}, the reference is $reply = $context['get_replies']() * * @return mixed The function returns the "next" message reply's details, or simply false if no replies were available, or no further replies are available. Assuming a reply can be returned, it will be a hash array in the following format: * <ul> * <li>id: numeric message id</li> * <li>member: hash array containing details of the poster; normally the return value from SMF's loadMemberContext() function. A minimal set of details is prepared if the poster holds no current SMF account. Common values: * <ul> * <li>name: User's name (falls back to the poster name specified in the replies table)</li> * <li>id: User's id</li> * <li>group: Name of the assigned group/post count group of the user</li> * <li>link: HTML for a hyperlink to their profile</li> * <li>email: Email address of the poster</li> * <li>ip: IP address of the poster</li> * </ul> * </li> * <li>body: censored, parsed for smileys and bbcode (in {@link shd_format_text()})</li> * <li>time: string of the time the reply was posted</li> * <li>timestamp: internal stored timestamp attached to the reply</li> * <li>is_staff: boolean value of whether the posting member is currently helpdesk staff</li> * <li>can_edit: boolean value reflecting if this reply can be edited</li> * <li>can_delete: boolean value reflecting if this reply can be deleted</li> * <li>can_restore: boolean value reflecting if this reply can be restored</li> * <li>ip_address: IP address used to post the message (not necessarily the user's normal IP address); if the user has moderate_forum_members permission, this returns a link to the track IP area, with the IP address as the link text, alternatively simply the IP address if not (is only displayed to helpdesk staff)</li> * <li>modified: may not be declared, if it is, the message was modified some time after posting, and the following data items are in the hash array within: * <ul> * <li>id: user id who edited the reply (not always available)</li> * <li>time: formatted string of the time the post was edited</li> * <li>timestamp: raw timestamp of the time the post was edited</li> * <li>name: user name of the editing user; if we have a definite user id, this should contain the current name, falling back to the previously stored name</li> * <li>link: if we have a known, valid user id for the post's editor, this will contain a link to their profile, with the link text using their current display name; alternatively it will contain a regular string which is the username stored with the edit.</li> * </ul> * </li> * </ul> * * @see shd_view_ticket() * @since 1.0 */ function shd_prepare_ticket_context() { global $settings, $txt, $modSettings, $scripturl, $options, $user_info, $smcFunc; global $memberContext, $context, $reply_request, $user_profile; if (empty($reply_request)) { return false; } $message = $smcFunc['db_fetch_assoc']($reply_request); if (!$message) { $smcFunc['db_free_result']($reply_request); return false; } if (!loadMemberContext($message['id_member'], true)) { // Notice this information isn't used anywhere else.... $memberContext[$message['id_member']]['name'] = $message['poster_name']; $memberContext[$message['id_member']]['id'] = 0; $memberContext[$message['id_member']]['group'] = $txt['guest_title']; $memberContext[$message['id_member']]['link'] = $message['poster_name']; $memberContext[$message['id_member']]['email'] = $message['poster_email']; $memberContext[$message['id_member']]['show_email'] = showEmailAddress(true, 0); $memberContext[$message['id_member']]['is_guest'] = true; $memberContext[$message['id_member']]['group_stars'] = ''; } $memberContext[$message['id_member']]['ip'] = $message['poster_ip']; censorText($message['body']); $message['body'] = shd_format_text($message['body'], $message['smileys_enabled'], 'shd_reply_' . $message['id_msg']); $output = array('id' => $message['id_msg'], 'member' => &$memberContext[$message['id_member']], 'time' => timeformat($message['poster_time']), 'timestamp' => forum_time(true, $message['poster_time']), 'body' => $message['body'], 'is_staff' => !empty($context['shd_is_staff'][$message['id_member']]), 'can_edit' => $message['message_status'] != MSG_STATUS_DELETED && !$context['ticket']['closed'] && !$context['ticket']['deleted'] && (shd_allowed_to('shd_edit_reply_any', $context['ticket']['dept']) || $message['id_member'] == $user_info['id'] && shd_allowed_to('shd_edit_reply_own', $context['ticket']['dept'])), 'can_delete' => $message['message_status'] != MSG_STATUS_DELETED && !$context['ticket']['closed'] && !$context['ticket']['deleted'] && (shd_allowed_to('shd_delete_reply_any', $context['ticket']['dept']) || $message['id_member'] == $user_info['id'] && shd_allowed_to('shd_delete_reply_own', $context['ticket']['dept'])), 'can_restore' => $message['message_status'] == MSG_STATUS_DELETED && !$context['ticket']['closed'] && !$context['ticket']['deleted'] && (shd_allowed_to('shd_restore_reply_any', $context['ticket']['dept']) || $message['id_member'] == $user_info['id'] && shd_allowed_to('shd_restore_reply_own', $context['ticket']['dept'])), 'can_permadelete' => $message['message_status'] == MSG_STATUS_DELETED && !$context['ticket']['closed'] && !$context['ticket']['deleted'] && shd_allowed_to('shd_delete_recycling', $context['ticket']['dept']), 'message_status' => $message['message_status'], 'link' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'] . '.msg' . $message['id_msg'] . '#msg' . $message['id_msg']); if (shd_allowed_to('shd_view_ip_any', $context['ticket']['dept']) || $message['id_member'] == $user_info['id'] && shd_allowed_to('shd_view_ip_own', $context['ticket']['dept'])) { $output['ip_address'] = $context['link_ip_address'] ? '<a href="' . $scripturl . '?action=trackip;searchip=' . $message['poster_ip'] . '">' . $message['poster_ip'] . '</a>' : $message['poster_ip']; } if (!empty($message['modified_time'])) { $output['modified'] = array('time' => timeformat($message['modified_time']), 'timestamp' => forum_time(true, $message['modified_time']), 'id' => !empty($user_profile[$message['modified_member']]) ? $message['modified_member'] : 0, 'name' => !empty($user_profile[$message['modified_member']]) ? $user_profile[$message['modified_member']]['real_name'] : $message['modified_name']); $output['modified']['link'] = shd_profile_link($output['modified']['name'], $output['modified']['id']); } if (!empty($context['ticket_start_newfrom']) && $context['ticket_start_newfrom'] == $message['id_msg']) { $output['is_new'] = true; } return $output; }