/** * Display a form for adding/editing a record * * @return void */ public function editTask() { $this->view->setLayout('edit'); $this->view->lists = array(); // Get resolutions $sr = new Resolution($this->database); $this->view->lists['resolutions'] = $sr->getResolutions(); $this->view->lists['severities'] = Utilities::getSeverities($this->config->get('severities')); $id = Request::getInt('id', 0); $this->view->row = new Query($this->database); $this->view->row->load($id); if (!$this->view->row->sort) { $this->view->row->sort = 'created'; } if (!$this->view->row->sort_dir) { $this->view->row->sort_dir = 'desc'; } include_once dirname(dirname(__DIR__)) . DS . 'models' . DS . 'conditions.php'; $con = new Conditions(); $this->view->conditions = $con->getConditions(); // Set any errors foreach ($this->getErrors() as $error) { $this->view->setError($error); } // Output the HTML $this->view->display(); }
</label> <?php echo Html::input('calendar', 'target_date', $this->row->get('target_date') != '0000-00-00 00:00:00' ? $this->escape(Date::of($this->row->get('target_date'))->toLocal('Y-m-d H:i:s')) : '', array('id' => 'field-target_date')); ?> </div> <div class="grid"> <div class="col span6"> <div class="input-wrap"> <label for="ticket-field-severity"> <?php echo Lang::txt('COM_SUPPORT_TICKET_COMMENT_SEVERITY'); ?> <select name="severity" id="ticket-field-severity"> <?php foreach (\Components\Support\Helpers\Utilities::getSeverities() as $severity) { ?> <option value="<?php echo $severity; ?> "<?php if ($severity == $this->row->get('severity')) { echo ' selected="selected"'; } ?> ><?php echo Lang::txt('COM_SUPPORT_TICKET_SEVERITY_' . strtoupper($severity)); ?> </option> <?php }
/** * Delete a record * * @param boolean $isSpam * @return void */ public function removeTask($isSpam = false) { // Check for request forgeries Request::checkToken(); // Incoming $id = Request::getInt('id', 0); $parentid = Request::getInt('parentid', 0); // Ensure we have an ID to work with if (!$id) { App::redirect(Route::url('index.php?option=' . $this->_option . '&controller=' . $this->_controller, false)); return; } $email = 1; // Turn off/on $gratitude = 1; // Turn off/on $message = ''; // Load the report $report = new ReportAbuse($this->database); $report->load($id); $report->reviewed = Date::toSql(); $report->reviewed_by = User::get('id'); $report->note = Request::getVar('note', ''); // Get the reported item $results = Event::trigger('support.getReportedItem', array($report->referenceid, $report->category, $parentid)); // Check the results returned for a reported item $reported = null; if ($results) { foreach ($results as $result) { if ($result) { $reported = $result[0]; } } } // Remove the reported item and any other related processes that need be performed $results = Event::trigger('support.deleteReportedItem', array($report->referenceid, $parentid, $report->category, $message)); if ($results) { foreach ($results as $result) { if ($result) { $message .= $result; } } } if ($isSpam) { $results = Event::trigger('antispam.onAntispamTrain', array($reported->text, $isSpam)); } // Mark abuse report as deleted $report->state = 2; if (!$report->store()) { throw new Exception($report->getError(), 500); } // Notify item owner if ($email) { $user = User::getInstance($reported->author); // Email "from" info $from = array('name' => Config::get('sitename') . ' ' . Lang::txt('COM_SUPPORT'), 'email' => Config::get('mailfrom'), 'multipart' => md5(date('U'))); // Email subject $subject = Lang::txt('COM_SUPPORT_REPORT_ABUSE_EMAIL_SUBJECT', Config::get('sitename')); // Plain text $eview = new View(array('base_path' => PATH_CORE . DS . 'components' . DS . 'com_support' . DS . 'site', 'name' => 'emails', 'layout' => 'abuse_plain')); $eview->option = $this->_option; $eview->controller = $this->_controller; $eview->reported = $reported; $eview->report = $report; $eview->author = $user; $plain = $eview->loadTemplate(false); $plain = str_replace("\n", "\r\n", $plain); // HTML $eview->setLayout('abuse_html'); $html = $eview->loadTemplate(); $html = str_replace("\n", "\r\n", $html); // Build message $message = new Message(); $message->setSubject($subject)->addFrom($from['email'], $from['name'])->addTo($user->get('email'), $user->get('name'))->addHeader('X-Component', 'com_support')->addHeader('X-Component-Object', 'abuse_item_removal'); $message->addPart($plain, 'text/plain'); $message->addPart($html, 'text/html'); // Send the email if (Utilities::checkValidEmail($user->get('email'))) { $message->send(); } } // Check the HUB configuration to see if banking is turned on $upconfig = Component::params('com_members'); $banking = $upconfig->get('bankAccounts'); // Give some points to whoever reported abuse if ($banking && $gratitude) { $BC = \Hubzero\Bank\Config::values(); $ar = $BC->get('abusereport'); // How many points? if ($ar) { $ruser = User::getInstance($report->created_by); if (is_object($ruser) && $ruser->get('id')) { $BTL = new \Hubzero\Bank\Teller($ruser->get('id')); $BTL->deposit($ar, Lang::txt('COM_SUPPORT_ACKNOWLEDGMENT_FOR_VALID_REPORT'), 'abusereport', $id); } } } // Redirect App::redirect(Route::url('index.php?option=' . $this->_option . '&controller=' . $this->_controller, false), Lang::txt('COM_SUPPORT_REPORT_ITEM_TAKEN_DOWN')); }
/** * Create a new comment * * @apiMethod POST * @apiUri /support/comments * @apiParameter { * "name": "ticket", * "description": "Id of the ticket to make a comment on", * "type": "integer", * "required": true, * "default": null * } * @apiParameter { * "name": "comment", * "description": "Comment text", * "type": "string", * "required": true, * "default": null * } * @apiParameter { * "name": "group", * "description": "Group to assign the ticket to (by alias)", * "type": "string", * "required": false, * "default": null * } * @apiParameter { * "name": "owner", * "description": "Id of the owner to assign ticket to", * "type": "integer", * "required": false, * "default": null * } * @apiParameter { * "name": "severity", * "description": "Severity of the ticket", * "type": "string", * "required": false, * "default": null * "allowed_values": "minor, normal, major, critical" * } * @apiParameter { * "name": "status", * "description": "Status of the ticket", * "type": "integer", * "required": false, * "default": null * } * @apiParameter { * "name": "target_date", * "description": "Target date for completion of ticket (YYYY-MM-DD hh:mm:ss)", * "type": "string", * "required": false, * "default": null * } * @apiParameter { * "name": "cc", * "description": "Comma seperated list of email addresses to email updates to", * "type": "string", * "required": false, * "default": submitter,owner * } * @apiParameter { * "name": "private", * "description": "Should the comment be flagged as private", * "type": "boolean", * "required": false, * "default": false * } * @apiParameter { * "name": "email_submitter", * "description": "Should the submitter be emailed about this comment", * "type": "boolean", * "required": false, * "default": false * } * @apiParameter { * "name": "email_owner", * "description": "Should the ticket owner be emailed about this comment", * "type": "boolean", * "required": false, * "default": false * } * @return void */ public function createTask() { $this->requiresAuthentication(); if (!$this->acl->check('create', 'comments')) { throw new Exception(Lang::txt('Not authorized'), 403); } $ticket_id = Request::getInt('ticket', null); if (!isset($ticket_id)) { throw new Exception(Lang::txt('Bad request - ticket ID required'), 400); } $comment_text = Request::getString('comment', ''); if ($comment_text == '') { throw new Exception(Lang::txt('Bad request - comment required'), 400); } $ticket = \Components\Support\Models\Orm\Ticket::oneOrFail($ticket_id); $comment = new \Components\Support\Models\Orm\Comment(); $changelog = new stdClass(); $comment->set('ticket', Request::get('ticket', '')); $comment->set('comment', nl2br(Request::get('comment'))); $comment->set('created_by', User::get('id')); $comment->set('access', Request::get('private', false) == 'true' ? 1 : 0); $changes = array(); foreach (['group', 'owner', 'severity', 'status', 'target_date', 'category'] as $index) { if (Request::get($index, null)) { if (Request::get($index) != $ticket->get($index)) { $temp = new stdClass(); $temp->field = $index; $temp->before = $ticket->get($index); $temp->after = Request::get($index); if ($index == 'status') { if ($ticket->get('status') == 0) { $status_model = new \Components\Support\Models\Orm\Status(); $status_model->set('title', 'Closed'); $status_model->set('open', 0); } else { $status_model = \Components\Support\Models\Orm\Status::oneOrFail(Request::get('status')); } if ($ticket->get('status') == 0) { $old_status = new \Components\Support\Models\Orm\Status(); $old_status->set('title', 'Closed'); $old_status->set('open', 0); } else { $old_status = \Components\Support\Models\Orm\Status::oneOrFail($ticket->get('status')); } $temp->before = $old_status->get('title'); $temp->after = $status_model->get('title'); $ticket->set('open', $status_model->get('open')); if ($status_model->get('get') == 'open' && $ticket->get('status', null) == 'closed') { $tiket->set('closed', '0000-00-00 00:00:00'); } if ($status_model->get('get') == 'closed' && $ticket->get('status', null) == 'open') { $ticket->set('closed', Date::toSql()); } } if ($index == 'owner') { $old_owner = User::getInstance($ticket->get('owner')); $new_owner = User::getInstance(Request::get('owner')); $temp->before = $old_owner->get('username'); $temp->after = $new_owner->get('username'); } $ticket->set($index, Request::get($index)); $changes[] = $temp; } } } $changelog->changes = $changes; if ($comment->get('comment')) { // If a comment was posted by the ticket submitter to a "waiting user response" ticket, change status. $user = User::getInstance(User::get('id')); if ($ticket->get('status') == 2 && $user->get('username') == $ticket->get('login')) { $ticket->set('status', 0); } } $comment->set('changelog', json_encode($changelog)); if (!$comment->save()) { throw new Exception(print_r($comment->getErrors(), 1), 500); } if (!$ticket->save()) { throw new Exception(print_r($ticket->getErrors(), 1), 500); } // There's now a ticket and a comment, lets add attachments \Components\Support\Helpers\Utilities::addAttachments($ticket->get('id'), $comment->get('id')); $msg = new stdClass(); $msg->id = $comment->get('id'); $msg->notified = $comment->get('changelog'); $this->send($msg, 200, 'OK'); /* $changlog->notifications = array(); if (Request::get('email_owner')) { $comment->addTo(array( 'role' => Lang::txt('COM_SUPPORT_COMMENT_SEND_EMAIL_OWNER'), 'name' => $ticket->get_owner->get('name'), 'email' => $ticket->get_owner->get('email'), 'id' => $ticket->get_owner->get('id') )); $changelog->notifications[] = json_encode(array('role'=>'Ticket owner', 'address'=>$ticket->get_owner()->get('email'), 'name'=>$ticket->get_owner()->get('name'))); } // Add any CCs to the e-mail list $cc = Request::get('cc', null); if ($cc) { $cc = explode(',', $cc); foreach ($cc) { $comment->addTo($cc, Lang::txt('COM_SUPPORT_COMMENT_SEND_EMAIL_CC')); } $changelog->cc = json_encode($cc); } // Check if the notify list has eny entries if (count($comment->to())) { include_once(PATH_CORE . DS . 'components' . DS . 'com_support' . DS . 'helpers' . DS . 'utilities.php'); $allowEmailResponses = $ticket->config('email_processing'); if ($allowEmailResponses) { try { $encryptor = new \Hubzero\Mail\Token(); } catch (Exception $e) { $allowEmailResponses = false; } } $subject = Lang::txt('COM_SUPPORT_EMAIL_SUBJECT_TICKET_COMMENT', $ticket->get('id')); $from = array( 'name' => Lang::txt('COM_SUPPORT_EMAIL_FROM', Config::get('sitename')), 'email' => Config::get('mailfrom'), 'multipart' => md5(date('U')) ); $message = array(); // Plain text email $eview = new \Hubzero\Mail\View(array( 'base_path' => PATH_CORE . '/components/com_support/site', 'name' => 'emails', 'layout' => 'comment_plain' )); $eview->option = 'com_support'; $eview->controller = 'tickets'; $eview->comment = $comment; $eview->ticket = $ticket; $eview->delimiter = ($allowEmailResponses ? '~!~!~!~!~!~!~!~!~!~!' : ''); $message['plaintext'] = $eview->loadTemplate(false); $message['plaintext'] = str_replace("\n", "\r\n", $message['plaintext']); // HTML email $eview->setLayout('comment_html'); $message['multipart'] = $eview->loadTemplate(); // Send e-mail to admin? foreach ($comment->to('ids') as $to) { if ($allowEmailResponses) { // The reply-to address contains the token $token = $encryptor->buildEmailToken(1, 1, $to['id'], $ticket->get('id')); $from['replytoemail'] = 'htc-' . $token . strstr(Config::get('mailfrom'), '@'); } // Get the user's email address if (!Event::trigger('xmessage.onSendMessage', array('support_reply_submitted', $subject, $message, $from, array($to['id']), 'com_support'))) { $this->setError(Lang::txt('COM_SUPPORT_ERROR_FAILED_TO_MESSAGE', $to['name'] . '(' . $to['role'] . ')')); } $comment->changelog()->notified( $to['role'], $to['name'], $to['email'] ); } foreach ($comment->to('emails') as $to) { if ($allowEmailResponses) { $token = $encryptor->buildEmailToken(1, 1, -9999, $ticket->get('id')); $email = array( $to['email'], 'htc-' . $token . strstr(Config::get('mailfrom'), '@') ); // In this case each item in email in an array, 1- To, 2:reply to address \Components\Support\Helpers\Utilities::sendEmail($email[0], $subject, $message, $from, $email[1]); } else { // email is just a plain 'ol string \Components\Support\Helpers\Utilities::sendEmail($to['email'], $subject, $message, $from); } $comment->changelog()->notified( $to['role'], $to['name'], $to['email'] ); } } $comment->set('changelog', json_encode($changelog)); $comment->save(); $ticket->save(); $msg = new stdClass; $msg->id = $comment->get('id'); $msg->notified = $comment->get('changelog'); $this->send($msg, 200, 'OK'); */ }
/** * Send emails reminding people of their open tickets * * @param object $job \Components\Cron\Models\Job * @return boolean */ public function sendTicketList(\Components\Cron\Models\Job $job) { $params = $job->get('params'); $database = App::get('db'); $sconfig = Component::params('com_support'); Lang::load('com_support') || Lang::load('com_support', PATH_CORE . DS . 'components' . DS . 'com_support' . DS . 'site'); $sql = "SELECT t.*, o.`name` AS owner_name FROM `#__support_tickets` AS t LEFT JOIN `#__users` AS o ON o.`id`=t.`owner`"; $where = array(); $where[] = "t.`type`=0"; if (is_object($params)) { if ($val = $params->get('support_ticketlist_open', 1)) { $where[] = "t.`open`=" . $val; } $statuses = array(); if (is_numeric($params->get('support_ticketlist_status1'))) { $statuses[] = $params->get('support_ticketlist_status1'); } if (is_numeric($params->get('support_ticketlist_status2'))) { $statuses[] = $params->get('support_ticketlist_status2'); } if (is_numeric($params->get('support_ticketlist_status3'))) { $statuses[] = $params->get('support_ticketlist_status3'); } if (count($statuses)) { $where[] = "t.`status` IN (" . implode(',', $statuses) . ")"; } if ($group = $params->get('support_ticketlist_group')) { $where[] = "t.`group`=" . $database->quote($group); } if ($owners = $params->get('support_ticketlist_owners')) { $usernames = explode(',', $owners); $usernames = array_map('trim', $usernames); foreach ($usernames as $k => $username) { $user = User::getInstance($username); $usernames[$k] = $database->quote($user->get('id')); } $where[] = "t.`owner` IN (" . implode(", ", $usernames) . ")"; } if ($severity = $params->get('support_ticketlist_severity')) { if ($severity != 'all') { $severities = explode(',', $severity); $severities = array_map('trim', $severities); foreach ($severities as $k => $severity) { $severities[$k] = $database->quote($severity); } $where[] = "t.`severity` IN (" . implode(", ", $severities) . ")"; } } if ($owned = intval($params->get('support_ticketlist_owned', 0))) { if ($owned == 1) { $where[] = "(t.`owner` IS NULL OR t.`owner`='0')"; } else { if ($owned == 2) { $where[] = "(t.`owner` IS NOT NULL AND t.`owner` !='0')"; } } } if ($submitters = $params->get('support_ticketlist_submitters')) { $usernames = explode(',', $submitters); $usernames = array_map('trim', $usernames); foreach ($usernames as $k => $username) { $usernames[$k] = $database->quote($username); } $where[] = "t.`login` IN (" . implode(", ", $usernames) . ")"; } if ($tags = $params->get('support_ticketlist_excludeTags')) { $tags = explode(',', $tags); $tags = array_map('trim', $tags); foreach ($tags as $k => $tag) { $tags[$k] = $database->quote($tag); } $where[] = "t.`id` NOT IN (\n\t\t\t\t\t\t\tSELECT jto.`objectid` FROM `#__tags_object` AS jto\n\t\t\t\t\t\t\tJOIN `#__tags` AS jt ON jto.`tagid`=jt.`id`\n\t\t\t\t\t\t\tWHERE jto.`tbl`='support'\n\t\t\t\t\t\t\tAND (\n\t\t\t\t\t\t\t\tjt.`tag` IN (" . implode(", ", $tags) . ") OR jt.`raw_tag` IN (" . implode(", ", $tags) . ")\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)"; } if ($tags = $params->get('support_ticketlist_includeTags')) { $tags = explode(',', $tags); $tags = array_map('trim', $tags); foreach ($tags as $k => $tag) { $tags[$k] = $database->quote($tag); } $where[] = "t.`id` IN (\n\t\t\t\t\t\t\tSELECT jto.`objectid` FROM `#__tags_object` AS jto\n\t\t\t\t\t\t\tJOIN `#__tags` AS jt ON jto.`tagid`=jt.`id`\n\t\t\t\t\t\t\tWHERE jto.`tbl`='support'\n\t\t\t\t\t\t\tAND (\n\t\t\t\t\t\t\t\tjt.`tag` IN (" . implode(", ", $tags) . ") OR jt.`raw_tag` IN (" . implode(", ", $tags) . ")\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)"; } if ($created = $params->get('support_ticketlist_created', '+week')) { $op = ''; switch ($created) { // Created before (older than) case '-day': $op = '<='; $timestamp = Date::modify('-1 day'); break; case '-week': $op = '<='; $timestamp = Date::modify('-1 week'); break; case '-2week': $op = '<='; $timestamp = Date::modify('-2 week'); break; case '-3week': $op = '<='; $timestamp = Date::modify('-3 week'); break; case '-month': $op = '<='; $timestamp = Date::modify('-1 month'); break; case '-6month': $op = '<='; $timestamp = Date::modify('-6 month'); break; case '-year': $op = '<='; $timestamp = Date::modify('-1 year'); break; // Created since (newer than) // Created since (newer than) case '+day': $op = '>='; $timestamp = Date::modify('-1 day'); break; case '+week': $op = '>='; $timestamp = Date::modify('-1 week'); break; case '+2week': $op = '>='; $timestamp = Date::modify('-2 week'); break; case '+3week': $op = '>='; $timestamp = Date::modify('-3 week'); break; case '+month': $op = '>='; $timestamp = Date::modify('-1 month'); break; case '+6month': $op = '>='; $timestamp = Date::modify('-6 month'); break; case '+year': $op = '>='; $timestamp = Date::modify('-1 year'); break; } if ($op) { $where[] = "t.`created`" . $op . $database->quote($timestamp->toSql()); } } if ($created = $params->get('support_ticketlist_activity', '--')) { $op = ''; switch ($created) { // Created before (older than) case '-day': $op = '<='; $timestamp = Date::modify('-1 day'); break; case '-week': $op = '<='; $timestamp = Date::modify('-1 week'); break; case '-2week': $op = '<='; $timestamp = Date::modify('-2 week'); break; case '-3week': $op = '<='; $timestamp = Date::modify('-3 week'); break; case '-month': $op = '<='; $timestamp = Date::modify('-1 month'); break; case '-6month': $op = '<='; $timestamp = Date::modify('-6 month'); break; case '-year': $op = '<='; $timestamp = Date::modify('-1 year'); break; case 'all': case '--': $op = ''; break; } if ($op) { $where[] = "(SELECT MAX(c.`created`) FROM `#__support_comments` AS c WHERE c.`ticket`=t.`id`) " . $op . $database->quote($timestamp->toSql()); } } } else { $where[] = "t.`open`=1"; } if (count($where) > 0) { $sql .= " WHERE " . implode(" AND ", $where); } $sql .= " ORDER BY t.`created` ASC LIMIT 0, 500"; $database->setQuery($sql); if (!($results = $database->loadObjectList())) { return true; } include_once PATH_CORE . DS . 'components' . DS . 'com_support' . DS . 'models' . DS . 'ticket.php'; if ($params->get('support_ticketlist_severity', 'all') != 'all') { $severities = explode(',', $params->get('support_ticketlist_severity', 'all')); } else { include_once PATH_CORE . DS . 'components' . DS . 'com_support' . DS . 'helpers' . DS . 'utilities.php'; $severities = \Components\Support\Helpers\Utilities::getSeverities($sconfig->get('severities')); } $from = array(); $from['name'] = Config::get('sitename') . ' ' . Lang::txt('COM_SUPPORT'); $from['email'] = Config::get('mailfrom'); $from['multipart'] = md5(date('U')); // Set mail additional args (mail return path - used for bounces) if ($host = Request::getVar('HTTP_HOST', '', 'server')) { $args = '-f hubmail-bounces@' . $host; } $subject = Lang::txt('COM_SUPPORT') . ': ' . Lang::txt('COM_SUPPORT_TICKETS'); $usernames = array(); if ($users = $params->get('support_ticketlist_notify')) { $usernames = explode(',', $users); $usernames = array_map('trim', $usernames); } $mailed = array(); foreach ($usernames as $owner) { if ($owner == '{config.mailfrom}') { $name = Config::get('mailfrom'); $email = Config::get('mailfrom'); } else { if (strstr($owner, '@')) { $name = $owner; $email = $owner; } else { // Get the user's account $user = User::getInstance($owner); if (!is_object($user) || !$user->get('id')) { continue; } $name = $user->get('name'); $email = $user->get('email'); } } // Try to ensure no duplicates if (in_array($email, $mailed)) { continue; } $eview = new \Hubzero\Mail\View(array('base_path' => PATH_CORE . DS . 'components' . DS . 'com_support' . DS . 'site', 'name' => 'emails', 'layout' => 'ticketlist_plain')); $eview->option = 'com_support'; $eview->controller = 'tickets'; $eview->delimiter = '~!~!~!~!~!~!~!~!~!~!'; $eview->boundary = $from['multipart']; $eview->tickets = $results; $eview->config = $sconfig; $plain = $eview->loadTemplate(false); $plain = str_replace("\n", "\r\n", $plain); // HTML $eview->setLayout('ticketlist_html'); $html = $eview->loadTemplate(); $html = str_replace("\n", "\r\n", $html); // Build message $message = new \Hubzero\Mail\Message(); $message->setSubject($subject)->addFrom($from['email'], $from['name'])->addTo($email, $name)->addHeader('X-Component', 'com_support')->addHeader('X-Component-Object', 'support_ticket_list'); $message->addPart($plain, 'text/plain'); $message->addPart($html, 'text/html'); // Send mail if (!$message->send()) { //$this->setError(Lang::txt('Failed to mail %s', $fullEmailAddress)); Log::error('CRON email failed: ' . Lang::txt('Failed to mail %s', $email)); } $mailed[] = $email; } return true; }
</th> <th scope="col" class="block"><?php echo Lang::txt('COM_SUPPORT_STATS_COL_AVERAGE'); ?> </th> </tr> </thead> <tbody> <tr> <td><?php echo number_format($user->total); ?> </td> <td class="block"> <?php $lifetime = \Components\Support\Helpers\Utilities::calculateAverageLife($user->tickets); ?> <?php echo isset($lifetime[0]) ? $lifetime[0] : 0; ?> <span><?php echo Lang::txt('COM_SUPPORT_STATS_DAYS'); ?> </span> <?php echo isset($lifetime[1]) ? $lifetime[1] : 0; ?> <span><?php echo Lang::txt('COM_SUPPORT_STATS_HOURS'); ?> </span>
/** * Display a form for processing tickets in a batch * * @return void */ public function batchTask() { Request::setVar('hidemainmenu', 1); // Incoming $this->view->ids = Request::getVar('id', array()); $this->view->tmpl = Request::getVar('tmpl', ''); $this->view->filters = Utilities::getFilters(); $this->view->lists = array(); // Get categories $sa = new Tables\Category($this->database); $this->view->lists['categories'] = $sa->find('list'); // Get severities $this->view->lists['severities'] = Utilities::getSeverities($this->config->get('severities')); $this->view->lists['owner'] = $this->_userSelect('owner', '', 1); // Output the HTML $this->view->display(); }
/** * Removes an item reported as abusive * * @param integer $referenceid ID of the database table row * @param integer $parentid If the element has a parent element * @param string $category Element type (determines table to look in) * @param string $message Message to user to append to * @return string */ public function deleteReportedItem($referenceid, $parentid, $category, $message) { if (!$this->_canHandle($category)) { return null; } $database = App::get('db'); switch ($category) { case 'answer': $database->setQuery("UPDATE `#__answers_responses` SET state='2' WHERE id=" . $referenceid); if (!$database->query()) { $this->setError($database->getErrorMsg()); return false; } $message .= Lang::txt('PLG_SUPPORT_ANSWERS_NOTIFY_ANSWER_REMOVED', $parentid); break; case 'question': $upconfig = Component::params('com_members'); $banking = $upconfig->get('bankAccounts'); $reward = 0; if ($banking) { $reward = $this->getReward($parentid); } $responders = array(); // Get all the answers for this question $database->setQuery("SELECT r.id, r.created_by FROM `#__answers_responses` AS r WHERE r.question_id=" . $referenceid); $answers = $database->loadObjectList(); if ($answers) { foreach ($answers as $answer) { // Delete response $database->setQuery("UPDATE `#__answers_responses` SET state='2' WHERE id=" . $answer->id); if (!$database->query()) { $this->setError($database->getErrorMsg()); return false; } // Collect responders names $responders[] = $answer->created_by; } } $database->setQuery("UPDATE `#__answers_questions` SET state='2', reward='0' WHERE id=" . $referenceid); if (!$database->query()) { $this->setError($database->getErrorMsg()); return false; } if ($banking && $reward) { // Send email to people who answered question with reward if ($responders) { foreach ($responders as $r) { $zuser = User::getInstance($r); if (is_object($zuser)) { if (\Components\Support\Helpers\Utilities::checkValidEmail($zuser->get('email')) && $email) { $admin_email = Config::get('mailfrom'); $sub = Lang::txt('PLG_SUPPORT_ANSWERS_SUBJECT', Config::get('sitename'), $referenceid); $from = Lang::txt('PLG_SUPPORT_ANSWERS_TITLE', Config::get('sitename')); $hub = array('email' => $admin_email, 'name' => $from); $mes = Lang::txt('PLG_SUPPORT_ANSWERS_BODY') . "\r\n"; $mes .= '----------------------------' . "\r\n\r\n"; $mes .= Lang::txt('PLG_SUPPORT_ANSWERS_QUESTION', $referenceid) . "\r\n"; \Components\Support\Helpers\Utilities::sendEmail($hub, $zuser->get('email'), $sub, $mes); } } } } // get id of asker $database->setQuery("SELECT created_by FROM `#__answers_questions` WHERE id=" . $parentid); $asker = $database->loadResult(); if ($asker) { $quser = User::getInstance($asker); if (is_object($quser)) { $asker_id = $quser->get('id'); } if (isset($asker_id)) { // Remove hold $sql = "DELETE FROM `#__users_transactions` WHERE category='answers' AND type='hold' AND referenceid=" . $parentid . " AND uid='" . $asker_id . "'"; $database->setQuery($sql); if (!$database->query()) { $this->setError($database->getErrorMsg()); return false; } // Make credit adjustment $BTL_Q = new \Hubzero\Bank\Teller($database, $asker_id); $credit = $BTL_Q->credit_summary(); $adjusted = $credit - $reward; $BTL_Q->credit_adjustment($adjusted); } } } $message .= Lang::txt('PLG_SUPPORT_ANSWERS_NOTIFY_QUESTION_REMOVED', $parentid); break; case 'answercomment': $comment = new \Hubzero\Item\Comment($database); $comment->load($referenceid); $comment->state = 2; if (!$comment->store()) { $this->setError($comment->getError()); return false; } $message .= Lang::txt('PLG_SUPPORT_ANSWERS_NOTIFY_COMMENT_REMOVED', $parentid); break; } return $message; }
/** * Create a new record * * @return object */ public function getConditions() { $conditions = new stdClass(); $conditions->owner = $this->_expression(array($this->_operator('=', 'is', true), $this->_operator('!=', 'is not', false), $this->_operator('LIKE \'%$1%\'', 'contains', false), $this->_operator('LIKE \'$1%\'', 'starts with', false), $this->_operator('LIKE \'%$1\'', 'ends with', false), $this->_operator('NOT LIKE \'%$1%\'', 'does not contain', false), $this->_operator('NOT LIKE \'$1%\'', 'does not start with', false), $this->_operator('NOT LIKE \'%$1\'', 'does not end with', false)), 'text'); // Groups $items = array($this->_value('*', Lang::txt('(any of mine)'), true)); if ($xgroups = \Hubzero\User\Helper::getGroups(User::get('id'), 'members')) { foreach ($xgroups as $xgroup) { $xgroup->description = trim($xgroup->description) ?: $xgroup->cn; $items[] = $this->_value($xgroup->cn, stripslashes($this->escape($xgroup->description)), false); } } $conditions->group = $this->_expression(array($this->_operator('=', 'is', true), $this->_operator('!=', 'is not', false), $this->_operator('LIKE \'%$1%\'', 'contains', false), $this->_operator('LIKE \'$1%\'', 'starts with', false), $this->_operator('LIKE \'%$1\'', 'ends with', false), $this->_operator('NOT LIKE \'%$1%\'', 'does not contain', false), $this->_operator('NOT LIKE \'$1%\'', 'does not start with', false), $this->_operator('NOT LIKE \'%$1\'', 'does not end with', false)), $items); $conditions->login = $this->_expression(array($this->_operator('=', 'is', true), $this->_operator('!=', 'is not', false), $this->_operator('LIKE \'%$1%\'', 'contains', false), $this->_operator('LIKE \'$1%\'', 'starts with', false), $this->_operator('LIKE \'%$1\'', 'ends with', false), $this->_operator('NOT LIKE \'%$1%\'', 'does not contain', false), $this->_operator('NOT LIKE \'$1%\'', 'does not start with', false), $this->_operator('NOT LIKE \'%$1\'', 'does not end with', false)), 'text'); $conditions->id = $this->_expression(array($this->_operator('=', 'is', true), $this->_operator('!=', 'is not', false), $this->_operator('lt', 'less than', false), $this->_operator('gt', 'grater than', false), $this->_operator('=lt', 'less than or equal to', false), $this->_operator('gt=', 'greater than or equal to', false)), 'text'); $conditions->report = $this->_expression(array($this->_operator('=', 'is', false), $this->_operator('!=', 'is not', false), $this->_operator('LIKE \'%$1%\'', 'contains', true), $this->_operator('LIKE \'$1%\'', 'starts with', false), $this->_operator('LIKE \'%$1\'', 'ends with', false), $this->_operator('NOT LIKE \'%$1%\'', 'does not contain', false), $this->_operator('NOT LIKE \'$1%\'', 'does not start with', false), $this->_operator('NOT LIKE \'%$1\'', 'does not end with', false)), 'text'); $conditions->open = $this->_expression(array($this->_operator('=', 'is', true), $this->_operator('!=', 'is not', false)), array($this->_value('1', 'open', true), $this->_value('0', 'closed', false))); $sr = new \Components\Support\Tables\Status($this->database); $status = $sr->find('list', array('sort' => 'open', 'sort_Dir' => 'DESC')); $items = array(); $items[] = $this->_value(0, $this->escape('open: New'), true); if (isset($status) && is_array($status)) { $switched = false; foreach ($status as $anode) { if (!$anode->open && !$switched) { $items[] = $this->_value(-1, $this->escape('closed: No resolution'), false); $switched = true; } $items[] = $this->_value($anode->id, $this->escape(($anode->open ? 'open: ' : 'closed: ') . stripslashes($anode->title)), false); } } $conditions->status = $this->_expression(array($this->_operator('=', 'is', true), $this->_operator('!=', 'is not', false)), $items); $conditions->created = $this->_expression(array($this->_operator('=', 'on', true), $this->_operator('lt', 'before', false), $this->_operator('gt', 'after', false)), 'text'); $conditions->closed = $this->_expression(array($this->_operator('=', 'on', true), $this->_operator('lt', 'before', false), $this->_operator('gt', 'after', false)), 'text'); $conditions->tag = $this->_expression(array($this->_operator('=', 'is', true), $this->_operator('!=', 'is not', false)), 'text'); $conditions->type = $this->_expression(array($this->_operator('=', 'is', true), $this->_operator('!=', 'is not', false)), array($this->_value('0', 'user submitted', true), $this->_value('1', 'automatic', false), $this->_value('3', 'tool', false))); $severities = Utilities::getSeverities($this->config->get('severities')); $items = 'text'; if (isset($severities) && is_array($severities)) { $items = array(); foreach ($severities as $severity) { $sel = false; if ($severity == 'normal') { $sel = true; } $items[] = $this->_value($severity, $severity, $sel); } } $conditions->severity = $this->_expression(array($this->_operator('=', 'is', true), $this->_operator('!=', 'is not', false)), $items); $sc = new Category($this->database); $categories = $sc->find('list'); $items = 'text'; if (isset($categories) && is_array($categories)) { $items = array(); foreach ($categories as $anode) { $sel = false; $items[] = $this->_value($this->escape($anode->alias), $this->escape(stripslashes($anode->title)), $sel); } } $conditions->category = $this->_expression(array($this->_operator('=', 'is', true), $this->_operator('!=', 'is not', false)), $items); return $conditions; }
/** * Display a form for adding/editing a record * * @return void */ public function editTask() { Request::setVar('hidemainmenu', 1); $this->view->lists = array(); $this->view->lists['severities'] = Utilities::getSeverities($this->config->get('severities')); $id = Request::getVar('id', array(0)); if (is_array($id)) { $id = !empty($id) ? $id[0] : 0; } $this->view->row = new Query($this->database); $this->view->row->load($id); if (!$this->view->row->sort) { $this->view->row->sort = 'created'; } if (!$this->view->row->sort_dir) { $this->view->row->sort_dir = 'desc'; } include_once dirname(dirname(__DIR__)) . DS . 'models' . DS . 'conditions.php'; $con = new Conditions(); $this->view->conditions = $con->getConditions(); // Set any errors foreach ($this->getErrors() as $error) { $this->view->setError($error); } // Output the HTML $this->view->setLayout('edit')->display(); }
/** * Create a new ticket * * @apiMethod POST * @apiUri /support/tickets * @apiParameter { * "name": "username", * "description": "The submitter's username", * "type": "string", * "required": false, * "default": null * } * @apiParameter { * "name": "name", * "description": "The submitter's name", * "type": "string", * "required": true, * "default": null * } * @apiParameter { * "name": "email", * "description": "The submitter's email address", * "type": "string", * "required": true, * "default": null * } * @apiParameter { * "name": "os", * "description": "The submitter's operating system", * "type": "string", * "required": false, * "default": "Unknown" * } * @apiParameter { * "name": "browser", * "description": "The submitter's browser type", * "type": "string", * "required": false, * "default": "Unknown" * } * @apiParameter { * "name": "report", * "description": "Description of the user's problem", * "type": "string", * "required": true, * "default": null * } * @apiParameter { * "name": "status", * "description": "The status code of the ticket", * "type": "integer", * "required": false, * "default": 0 * } * @apiParameter { * "name": "severity", * "description": "The severity of the issue", * "type": "string", * "required": false, * "default": "normal" , * "allowed_values": "minor, normal, major, critical" * } * @apiParameter { * "name": "owner", * "description": "The id of the user to assign this ticket to", * "type": "integer", * "required": false, * "default": 0 * } * @apiParameter { * "name": "group", * "description": "Alias of the group to assign the ticket to", * "type": "string", * "required": false, * "default": null * } * @apiParameter { * "name": "files", * "description": "***STUB*** NOT WORKING", * "type": "binary", * "required": false, * "default": null * } * @return void */ public function createTask() { //get the userid and attempt to load user profile $userid = User::get('id'); $result = User::getInstance($userid); //make sure we have a user if (!$result || !$result->get('id')) { throw new Exception(Lang::txt('User not found.'), 500); } //check required fields if (!Request::get('name', null)) { throw new Exception(Lang::txt('COM_SUPPORT_ERROR_NAME_NOT_FOUND'), 404); } if (!Request::get('email', null)) { throw new Exception(Lang::txt('COM_SUPPORT_ERROR_EMAIL_NOT_FOUND'), 404); } if (!Request::get('report', null)) { throw new Exception(Lang::txt('COM_SUPPORT_ERROR_REPORT_NOT_FOUND'), 404); } // Initiate class and bind data to database fields $ticket = new \Components\Support\Models\Orm\Ticket(); // Set the column values for our new row $ticket->set('status', Request::getInt('status', 0)); //check if a username was sent, otherwise fill in with the session's username if (Request::getString('username', null)) { $ticket->set('login', Request::get('username', 'None')); } else { $ticket->set('login', $result->get('username')); } //setting more optional values $ticket->set('severity', Request::get('severity', 'normal')); $ticket->set('owner', Request::get('owner', 0)); //check if the report was good $ticket->set('report', Request::get('report', '', 'none', 2)); if (!$ticket->get('report')) { throw new Exception(Lang::txt('Error: Report contains no text.'), 500); } // build the summary $summary = substr($ticket->get('report'), 0, 70); if (strlen($summary) >= 70) { $summary .= '...'; } $ticket->set('summary', $summary); //continue setting values $ticket->set('email', Request::get('email', 'None')); $ticket->set('name', Request::get('name', 'None')); $ticket->set('os', Request::get('os', 'Unknown')); $ticket->set('browser', Request::get('browser', 'Unknown')); $ticket->set('ip', Request::ip()); //$ticket->set('hostname', gethostbyaddr(Request::get('REMOTE_ADDR','','server'))); $ticket->set('uas', 'API Submission'); $ticket->set('referrer', '/api/v2.0/support/tickets'); $ticket->set('instances', 1); $ticket->set('section', 1); $ticket->set('group', Request::get('group', '')); $ticket->set('open', 1); // Save the data if (!$ticket->save()) { throw new Exception($ticket->getErrors(), 500); } // Now we have a ticket ID, lets check for attachments \Components\Support\Helpers\Utilities::addAttachments($ticket->get('id')); // Set the response $msg = new stdClass(); $msg->submitted = $ticket->get('created'); $msg->ticket = $ticket->get('id'); $this->send($msg, 201); }
/** * Updates a ticket with any changes and adds a new comment * * @return void */ public function updateTask() { // Make sure we are still logged in if (User::isGuest()) { $return = base64_encode(Route::url('index.php?option=' . $this->_option . '&controller=' . $this->_controller . '&task=' . $this->_task, false, true)); App::redirect(Route::url('index.php?option=com_users&view=login&return=' . $return, false)); return; } // Check for request forgeries Request::checkToken(); // Incoming $id = Request::getInt('id', 0, 'post'); if (!$id) { throw new Exception(Lang::txt('COM_SUPPORT_ERROR_MISSING_TICKET_ID'), 500); } $comment = Request::getVar('comment', '', 'post', 'none', 2); $incoming = Request::getVar('ticket', array(), 'post'); $incoming = array_map('trim', $incoming); if (isset($incoming['target_date'])) { if (!$incoming['target_date']) { $incoming['target_date'] = '0000-00-00 00:00:00'; } else { $incoming['target_date'] = Date::of($incoming['target_date'], Config::get('offset'))->toSql(); } } // Load the old ticket so we can compare for the changelog $old = new Ticket($id); $old->set('tags', $old->tags('string')); // Initiate class and bind posted items to database fields $row = new Ticket($id); if (!$row->bind($incoming)) { throw new Exception($row->getError(), 500); } $rowc = new Comment(); $rowc->set('ticket', $id); // Check if changes were made inbetween the time the comment was started and posted $started = Request::getVar('started', Date::toSql(), 'post'); $lastcomment = $row->comments('list', array('sort' => 'created', 'sort_Dir' => 'DESC', 'limit' => 1, 'start' => 0, 'ticket' => $id))->first(); if ($lastcomment && $lastcomment->created() > $started) { $rowc->set('comment', $comment); $this->setError(Lang::txt('Changes were made to this ticket in the time since you began commenting/making changes. Please review your changes before submitting.')); return $this->ticketTask($rowc); } // Update ticket status if necessary if ($id && isset($incoming['status']) && $incoming['status'] == 0) { $row->set('open', 0); $row->set('resolved', Lang::txt('COM_SUPPORT_COMMENT_OPT_CLOSED')); } $row->set('open', $row->status('open')); // Check content if (!$row->check()) { throw new Exception($row->getError(), 500); } // If an existing ticket AND closed AND previously open if ($id && !$row->get('open') && $row->get('open') != $old->get('open')) { // Record the closing time $row->set('closed', Date::toSql()); } // Incoming comment if ($comment) { // If a comment was posted by the ticket submitter to a "waiting user response" ticket, change status. if ($row->isWaiting() && User::get('username') == $row->get('login')) { $row->open(); } } // Store new content if (!$row->store()) { throw new Exception($row->getError(), 500); } // Save the tags $row->tag(Request::getVar('tags', '', 'post'), User::get('id'), 1); $row->set('tags', $row->tags('string')); // Create a new support comment object and populate it $access = Request::getInt('access', 0); $rowc->set('ticket', $id); $rowc->set('comment', nl2br($comment)); $rowc->set('created', Date::toSql()); $rowc->set('created_by', User::get('id')); $rowc->set('access', $access); // Compare fields to find out what has changed for this ticket and build a changelog $rowc->changelog()->diff($old, $row); $rowc->changelog()->cced(Request::getVar('cc', '')); // Save the data if (!$rowc->store()) { throw new Exception($rowc->getError(), 500); } Event::trigger('support.onTicketUpdate', array($row, $rowc)); $attach = new Tables\Attachment($this->database); if ($tmp = Request::getInt('tmp_dir')) { $attach->updateCommentId($tmp, $rowc->get('id')); } $attachment = $this->uploadTask($row->get('id'), $rowc->get('id')); // Only do the following if a comment was posted // otherwise, we're only recording a changelog if ($rowc->get('comment') || $row->get('owner') != $old->get('owner') || $row->get('group') != $old->get('group') || $rowc->attachments()->total() > 0) { // Send e-mail to ticket submitter? if (Request::getInt('email_submitter', 0) == 1) { // Is the comment private? If so, we do NOT send e-mail to the // submitter regardless of the above setting if (!$rowc->isPrivate()) { $rowc->addTo(array('role' => Lang::txt('COM_SUPPORT_COMMENT_SEND_EMAIL_SUBMITTER'), 'name' => $row->submitter('name'), 'email' => $row->submitter('email'), 'id' => $row->submitter('id'))); } } // Send e-mail to ticket owner? if (Request::getInt('email_owner', 0) == 1) { if ($old->get('owner') && $row->get('owner') != $old->get('owner')) { $rowc->addTo(array('role' => Lang::txt('COM_SUPPORT_COMMENT_SEND_EMAIL_PRIOR_OWNER'), 'name' => $old->owner('name'), 'email' => $old->owner('email'), 'id' => $old->owner('id'))); } if ($row->get('owner')) { $rowc->addTo(array('role' => Lang::txt('COM_SUPPORT_COMMENT_SEND_EMAIL_OWNER'), 'name' => $row->owner('name'), 'email' => $row->owner('email'), 'id' => $row->owner('id'))); } elseif ($row->get('group')) { $group = \Hubzero\User\Group::getInstance($row->get('group')); if ($group) { foreach ($group->get('managers') as $manager) { $manager = User::getInstance($manager); if (!$manager || !$manager->get('id')) { continue; } $rowc->addTo(array('role' => Lang::txt('COM_SUPPORT_COMMENT_SEND_EMAIL_GROUPMANAGER'), 'name' => $manager->get('name'), 'email' => $manager->get('email'), 'id' => $manager->get('id'))); } } } } // Add any CCs to the e-mail list foreach ($rowc->changelog()->get('cc') as $cc) { $rowc->addTo($cc, Lang::txt('COM_SUPPORT_COMMENT_SEND_EMAIL_CC')); } // Message people watching this ticket, // but ONLY if the comment was NOT marked private foreach ($row->watchers() as $watcher) { $this->acl->setUser($watcher->user_id); if (!$rowc->isPrivate() || $rowc->isPrivate() && $this->acl->check('read', 'private_comments')) { $rowc->addTo($watcher->user_id, 'watcher'); } } $this->acl->setUser(User::get('id')); $recipients = array(['support.tickets', 1]); if (count($rowc->to())) { $this->config->set('email_terse', Request::getInt('email_terse', 0)); $allowEmailResponses = $this->config->get('email_processing'); if ($this->config->get('email_terse')) { $allowEmailResponses = false; } if ($allowEmailResponses) { try { $encryptor = new \Hubzero\Mail\Token(); } catch (Exception $e) { $allowEmailResponses = false; } } // Build e-mail components $subject = Lang::txt('COM_SUPPORT_EMAIL_SUBJECT_TICKET_COMMENT', $row->get('id')); $from = array('name' => Lang::txt('COM_SUPPORT_EMAIL_FROM', Config::get('sitename')), 'email' => Config::get('mailfrom'), 'multipart' => md5(date('U'))); $message = array(); // Plain text email $eview = new \Hubzero\Mail\View(array('name' => 'emails', 'layout' => 'comment_plain')); $eview->option = $this->_option; $eview->controller = $this->_controller; $eview->comment = $rowc; $eview->ticket = $row; $eview->config = $this->config; $eview->delimiter = $allowEmailResponses ? '~!~!~!~!~!~!~!~!~!~!' : ''; $message['plaintext'] = $eview->loadTemplate(false); $message['plaintext'] = str_replace("\n", "\r\n", $message['plaintext']); // HTML email $eview->setLayout('comment_html'); $message['multipart'] = $eview->loadTemplate(); $message['multipart'] = str_replace("\n", "\r\n", $message['multipart']); $message['attachments'] = array(); if (!$this->config->get('email_terse')) { foreach ($rowc->attachments() as $attachment) { if ($attachment->size() < 2097152) { $message['attachments'][] = $attachment->link('filepath'); } } } foreach ($rowc->to('ids') as $to) { $recipients[] = ['user', $to['id']]; if ($allowEmailResponses) { // The reply-to address contains the token $token = $encryptor->buildEmailToken(1, 1, $to['id'], $id); $from['replytoemail'] = 'htc-' . $token . strstr(Config::get('mailfrom'), '@'); } // Get the user's email address if (!Event::trigger('xmessage.onSendMessage', array('support_reply_submitted', $subject, $message, $from, array($to['id']), $this->_option))) { $this->setError(Lang::txt('COM_SUPPORT_ERROR_FAILED_TO_MESSAGE', $to['name'] . '(' . $to['role'] . ')')); } // Watching should be anonymous if ($to['role'] == 'watcher') { continue; } $rowc->changelog()->notified($to['role'], $to['name'], $to['email']); } foreach ($rowc->to('emails') as $to) { if ($allowEmailResponses) { $token = $encryptor->buildEmailToken(1, 1, -9999, $id); $email = array($to['email'], 'htc-' . $token . strstr(Config::get('mailfrom'), '@')); // In this case each item in email in an array, 1- To, 2:reply to address Utilities::sendEmail($email[0], $subject, $message, $from, $email[1]); } else { // email is just a plain 'ol string Utilities::sendEmail($to['email'], $subject, $message, $from); } // Watching should be anonymous if ($to['role'] == 'watcher') { continue; } $rowc->changelog()->notified($to['role'], $to['name'], $to['email']); } } else { // Force entry to private if no comment or attachment was made if (!$rowc->get('comment') && $rowc->attachments()->total() <= 0) { $rowc->set('access', 1); } } // Were there any changes? if (count($rowc->changelog()->get('notifications')) > 0 || $access != $rowc->get('access')) { if (!$rowc->store()) { throw new Exception($rowc->getError(), 500); } } $desc = Lang::txt('COM_SUPPORT_ACTIVITY_TICKET_UPDATED', '<a href="' . Route::url($row->link()) . '">#' . $row->get('id') . ' - ' . $row->get('summary') . '</a>'); if ($rowc->get('comment')) { $desc = Lang::txt('COM_SUPPORT_ACTIVITY_COMMENT_CREATED', $rowc->get('id'), '<a href="' . Route::url($row->link()) . '">#' . $row->get('id') . ' - ' . $row->get('summary') . '</a>'); } Event::trigger('system.logActivity', ['activity' => ['action' => 'created', 'scope' => 'support.ticket.comment', 'scope_id' => $rowc->get('id'), 'description' => $desc, 'details' => array('id' => $row->get('id'), 'summary' => $row->get('summary'), 'url' => Route::url($row->link()), 'comment' => $rowc->get('id'))], 'recipients' => $recipients]); } // Display the ticket with changes, new comment App::redirect(Route::url('index.php?option=' . $this->_option . '&controller=' . $this->_controller . '&task=ticket&id=' . $id), $this->getError() ? $this->getError() : null, $this->getError() ? 'error' : null); }
/** * Create a new comment * * @apiMethod POST * @apiUri /support/{ticket}/comments * @apiParameter { * "name": "scope", * "description": "Scope type (group, member, etc.)", * "type": "string", * "required": true, * "default": null * } * @apiParameter { * "name": "scope_id", * "description": "Scope object ID", * "type": "integer", * "required": true, * "default": null * } * @apiParameter { * "name": "title", * "description": "Entry title", * "type": "string", * "required": true, * "default": null * } * @apiParameter { * "name": "alias", * "description": "Entry alias", * "type": "string", * "required": false, * "default": null * } * @return void */ public function createTask() { $this->requiresAuthentication(); if (!$this->acl->check('create', 'comments')) { throw new Exception(Lang::txt('Not authorized'), 403); } $ticket_id = Request::getInt('ticket', 0, 'post'); // Load the old ticket so we can compare for the changelog $old = new \Components\Support\Models\Ticket($ticket_id); $old->set('tags', $old->tags('string')); if (!$old->exists()) { $this->errorMessage(500, Lang::txt('Ticket "%s" does not exist.', $ticket_id)); return; } // Initiate class and bind posted items to database fields $ticket = new \Components\Support\Models\Ticket($ticket_id); $ticket->set('status', Request::getInt('status', $ticket->get('status'), 'post')); $ticket->set('open', Request::getInt('open', $ticket->get('open'), 'post')); $ticket->set('category', Request::getInt('category', $ticket->get('category'), 'post')); $ticket->set('severity', Request::getVar('severity', $ticket->get('severity'), 'post')); $ticket->set('owner', Request::getVar('owner', $ticket->get('owner'), 'post')); $ticket->set('group', Request::getVar('group', $ticket->get('group'), 'post')); // If an existing ticket AND closed AND previously open if ($ticket_id && !$ticket->get('open') && $ticket->get('open') != $old->get('open')) { // Record the closing time $ticket->set('closed', Date::toSql()); } // Any tags? if ($tags = trim(Request::getVar('tags', '', 'post'))) { $ticket->tag($tags, $user->get('uidNumber')); $ticket->set('tags', $ticket->tags('string')); } // Store new content if (!$ticket->store()) { $this->errorMessage(500, $ticket->getError()); return; } // Create a new comment $comment = new \Components\Support\Models\Comment(); $comment->set('ticket', $ticket->get('id')); $comment->set('comment', nl2br(Request::getVar('comment', '', 'post', 'none', 2))); if ($comment->get('comment')) { // If a comment was posted by the ticket submitter to a "waiting user response" ticket, change status. if ($ticket->isWaiting() && $user->get('username') == $ticket->get('login')) { $ticket->open(); } } $comment->set('created', Date::toSql()); $comment->set('created_by', $user->get('uidNumber')); $comment->set('access', Request::getInt('access', 0, 'post')); // Compare fields to find out what has changed for this ticket and build a changelog $comment->changelog()->diff($old, $ticket); $comment->changelog()->cced(Request::getVar('cc', '', 'post')); // Store new content if (!$comment->store()) { $this->errorMessage(500, $comment->getError()); return; } if ($ticket->get('owner')) { $comment->addTo(array('role' => Lang::txt('COM_SUPPORT_COMMENT_SEND_EMAIL_OWNER'), 'name' => $ticket->owner('name'), 'email' => $ticket->owner('email'), 'id' => $ticket->owner('id'))); } // Add any CCs to the e-mail list foreach ($comment->changelog()->get('cc') as $cc) { $comment->addTo($cc, Lang::txt('COM_SUPPORT_COMMENT_SEND_EMAIL_CC')); } // Check if the notify list has eny entries if (count($comment->to())) { include_once PATH_CORE . DS . 'components' . DS . 'com_support' . DS . 'helpers' . DS . 'utilities.php'; $allowEmailResponses = $ticket->config('email_processing'); if ($allowEmailResponses) { try { $encryptor = new \Hubzero\Mail\Token(); } catch (Exception $e) { $allowEmailResponses = false; } } $subject = Lang::txt('COM_SUPPORT_EMAIL_SUBJECT_TICKET_COMMENT', $ticket->get('id')); $from = array('name' => Lang::txt('COM_SUPPORT_EMAIL_FROM', Config::get('sitename')), 'email' => Config::get('mailfrom'), 'multipart' => md5(date('U'))); $message = array(); // Plain text email $eview = new \Hubzero\Mail\View(array('base_path' => PATH_CORE . '/components/com_support/site', 'name' => 'emails', 'layout' => 'comment_plain')); $eview->option = 'com_support'; $eview->controller = 'tickets'; $eview->comment = $comment; $eview->ticket = $ticket; $eview->delimiter = $allowEmailResponses ? '~!~!~!~!~!~!~!~!~!~!' : ''; $message['plaintext'] = $eview->loadTemplate(false); $message['plaintext'] = str_replace("\n", "\r\n", $message['plaintext']); // HTML email $eview->setLayout('comment_html'); $message['multipart'] = $eview->loadTemplate(); // Send e-mail to admin? foreach ($comment->to('ids') as $to) { if ($allowEmailResponses) { // The reply-to address contains the token $token = $encryptor->buildEmailToken(1, 1, $to['id'], $ticket->get('id')); $from['replytoemail'] = 'htc-' . $token . strstr(Config::get('mailfrom'), '@'); } // Get the user's email address if (!Event::trigger('xmessage.onSendMessage', array('support_reply_submitted', $subject, $message, $from, array($to['id']), 'com_support'))) { $this->setError(Lang::txt('COM_SUPPORT_ERROR_FAILED_TO_MESSAGE', $to['name'] . '(' . $to['role'] . ')')); } $comment->changelog()->notified($to['role'], $to['name'], $to['email']); } foreach ($comment->to('emails') as $to) { if ($allowEmailResponses) { $token = $encryptor->buildEmailToken(1, 1, -9999, $ticket->get('id')); $email = array($to['email'], 'htc-' . $token . strstr(Config::get('mailfrom'), '@')); // In this case each item in email in an array, 1- To, 2:reply to address \Components\Support\Helpers\Utilities::sendEmail($email[0], $subject, $message, $from, $email[1]); } else { // email is just a plain 'ol string \Components\Support\Helpers\Utilities::sendEmail($to['email'], $subject, $message, $from); } $comment->changelog()->notified($to['role'], $to['name'], $to['email']); } } // Were there any changes? if (count($comment->changelog()->get('notifications')) > 0 || count($comment->changelog()->get('cc')) > 0 || count($comment->changelog()->get('changes')) > 0) { // Save the data if (!$comment->store()) { $this->errorMessage(500, $comment->getError()); return; } } $msg = new stdClass(); $msg->ticket = $ticket->get('id'); $msg->comment = $comment->get('id'); $msg->notified = $comment->changelog()->get('notifications'); $this->setMessageType(Request::getVar('format', 'json')); $this->send($msg, 200, 'OK'); }