Ejemplo n.º 1
0
 /**
  * Saves a trouble report as a ticket
  *
  * @return  void
  */
 public function saveTask()
 {
     // Check for request forgeries
     Request::checkToken();
     $live_site = rtrim(Request::base(), '/');
     // Trigger any events that need to be called before session stop
     Event::trigger('support.onPreTicketSubmission', array());
     // Incoming
     $no_html = Request::getInt('no_html', 0);
     $verified = Request::getInt('verified', 0);
     if (!isset($_POST['reporter']) || !isset($_POST['problem'])) {
         // This really, REALLY shouldn't happen.
         throw new Exception(Lang::txt('COM_SUPPORT_ERROR_MISSING_DATA'), 400);
     }
     $reporter = Request::getVar('reporter', array(), 'post', 'none', 2);
     $problem = Request::getVar('problem', array(), 'post', 'none', 2);
     //$reporter = array_map('trim', $_POST['reporter']);
     //$problem  = array_map('trim', $_POST['problem']);
     // Normally calling Request::getVar calls _cleanVar, but b/c of the way this page processes the posts
     // (with array square brackets in the html names) against the $_POST collection, we explicitly
     // call the clean_var function on these arrays after fetching them
     //$reporter = array_map(array('Request', '_cleanVar'), $reporter);
     //$problem  = array_map(array('Request', '_cleanVar'), $problem);
     // [!] zooley - Who added this? Why?
     // Reporter login can only be for authenticated users -- ignore any form submitted login names
     //$reporterLogin = $this->_getUser();
     //$reporter['login'] = $reporterLogin['login'];
     // Probably redundant after the change to call Request::_cleanVar change above, It is a bit hard to
     // tell if the Joomla  _cleanvar function does enough to allow us to remove the purifyText call
     $reporter = array_map(array('\\Hubzero\\Utility\\Sanitize', 'stripAll'), $reporter);
     //$problem  = array_map(array('\\Hubzero\\Utility\\Sanitize', 'stripAll'), $problem);
     $reporter['name'] = trim($reporter['name']);
     $reporter['email'] = trim($reporter['email']);
     $problem['long'] = trim($problem['long']);
     // Make sure email address is valid
     $validemail = Validate::email($reporter['email']);
     // Set page title
     $this->_buildTitle();
     $this->view->title = $this->_title;
     // Set the pathway
     $this->_buildPathway();
     // Trigger any events that need to be called
     $customValidation = true;
     $result = Event::trigger('support.onValidateTicketSubmission', array($reporter, $problem));
     $customValidation = is_array($result) && !empty($result) ? $result[0] : $customValidation;
     // Check for some required fields
     if (!$reporter['name'] || !$reporter['email'] || !$validemail || !$problem['long'] || !$customValidation) {
         Request::setVar('task', 'new');
         // Output form with error messages
         if (!$reporter['name'] || !$reporter['email'] || !$problem['long']) {
             $this->setError(Lang::txt('COM_SUPPORT_ERROR_MISSING_DATA'));
         }
         if (!$validemail) {
             $this->setError(Lang::txt('COM_SUPPORT_ERROR_INVALID_EMAIL'));
         }
         if (!$customValidation) {
             $this->setError(Lang::txt('COM_SUPPORT_ERROR_INVALID_DATA'));
         }
         foreach ($this->getErrors() as $error) {
             $this->view->setError($error);
         }
         return $this->newTask();
     }
     // Get the user's IP
     $ip = Request::ip();
     $hostname = gethostbyaddr(Request::getVar('REMOTE_ADDR', '', 'server'));
     if (!$verified) {
         // Check CAPTCHA
         $validcaptchas = Event::trigger('support.onValidateCaptcha');
         if (count($validcaptchas) > 0) {
             foreach ($validcaptchas as $validcaptcha) {
                 if (!$validcaptcha) {
                     $this->setError(Lang::txt('COM_SUPPORT_ERROR_INVALID_CAPTCHA'));
                 }
             }
         }
     }
     // Are they verified?
     if (!$verified) {
         // Quick spam filter
         $spam = $this->_detectSpam($problem['long'], $ip);
         if ($spam) {
             $this->setError(Lang::txt('COM_SUPPORT_ERROR_FLAGGED_AS_SPAM'));
             return;
         }
         // Quick bot check
         $botcheck = Request::getVar('botcheck', '');
         if ($botcheck) {
             $this->setError(Lang::txt('COM_SUPPORT_ERROR_INVALID_BOTCHECK'));
             return;
         }
     }
     // Check for errors
     // If any found, push back into the submission form view
     if ($this->getError()) {
         if ($no_html) {
             // Output error messages (AJAX)
             $this->view->setLayout('error');
             if ($this->getError()) {
                 $this->view->setError($this->getError());
             }
             $this->view->display();
             return;
         } else {
             Request::setVar('task', 'new');
             $this->view->setError($this->getError());
             return $this->newTask();
         }
     }
     // Cut suggestion at 70 characters
     if (!$problem['short'] && $problem['long']) {
         $problem['short'] = substr($problem['long'], 0, 70);
         if (strlen($problem['short']) >= 70) {
             $problem['short'] .= '...';
         }
     }
     $group = isset($problem['group']) ? $problem['group'] : '';
     // Initiate class and bind data to database fields
     $row = new Ticket();
     $row->set('open', 1);
     $row->set('status', 0);
     $row->set('created', Date::toSql());
     $row->set('login', $reporter['login']);
     $row->set('severity', isset($problem['severity']) ? $problem['severity'] : 'normal');
     $row->set('owner', isset($problem['owner']) ? $problem['owner'] : null);
     $row->set('category', isset($problem['category']) ? $problem['category'] : '');
     $row->set('summary', $problem['short']);
     $row->set('report', $problem['long']);
     $row->set('resolved', isset($problem['resolved']) ? $problem['resolved'] : null);
     $row->set('email', $reporter['email']);
     $row->set('name', $reporter['name']);
     $row->set('os', $problem['os'] . ' ' . $problem['osver']);
     $row->set('browser', $problem['browser'] . ' ' . $problem['browserver']);
     $row->set('ip', $ip);
     $row->set('hostname', $hostname);
     $row->set('uas', Request::getVar('HTTP_USER_AGENT', '', 'server'));
     $row->set('referrer', base64_decode($problem['referer']));
     $row->set('cookies', Request::getVar('sessioncookie', '', 'cookie') ? 1 : 0);
     $row->set('instances', 1);
     $row->set('section', 1);
     $row->set('group', $group);
     if (isset($incoming['target_date'])) {
         if (!$incoming['target_date']) {
             $row->set('target_date', '0000-00-00 00:00:00');
         } else {
             $row->set('target_date', Date::of($incoming['target_date'], Config::get('offset'))->toSql());
         }
     }
     // check if previous ticket submitted is the same as this one.
     $ticket = new Tables\Ticket($this->database);
     $filters = array('status' => 'new', 'sort' => 'id', 'sortdir' => 'DESC', 'limit' => '1', 'start' => 0);
     $prevSubmission = $ticket->getTickets($filters, false);
     // for the first ticket ever
     if (isset($prevSubmission[0]) && $prevSubmission[0]->report == $row->get('report') && time() - strtotime($prevSubmission[0]->created) <= 15) {
         $this->setError(Lang::txt('COM_SUPPORT_TICKET_DUPLICATE_DETECTION'));
         return $this->newTask($row);
     }
     // Save the data
     if (!$row->store()) {
         $this->setError($row->getError());
     }
     $attachment = $this->uploadTask($row->get('id'));
     // Save tags
     $row->set('tags', Request::getVar('tags', '', 'post'));
     $row->tag($row->get('tags'), User::get('id'), 1);
     // Get any set emails that should be notified of ticket submission
     $defs = explode(',', $this->config->get('emails', '{config.mailfrom}'));
     if ($defs) {
         $message = new \Hubzero\Mail\Message();
         $message->setSubject(Config::get('sitename') . ' ' . Lang::txt('COM_SUPPORT_EMAIL_SUBJECT_NEW_TICKET', $row->get('id')));
         $message->addFrom(Config::get('mailfrom'), Config::get('sitename') . ' ' . Lang::txt(strtoupper($this->_option)));
         // Plain text email
         $eview = new \Hubzero\Mail\View(array('name' => 'emails', 'layout' => 'ticket_plain'));
         $eview->option = $this->_option;
         $eview->controller = $this->_controller;
         $eview->ticket = $row;
         $eview->config = $this->config;
         $eview->delimiter = '';
         $plain = $eview->loadTemplate(false);
         $plain = str_replace("\n", "\r\n", $plain);
         $message->addPart($plain, 'text/plain');
         // HTML email
         $eview->setLayout('ticket_html');
         $html = $eview->loadTemplate();
         $html = str_replace("\n", "\r\n", $html);
         if (!$this->config->get('email_terse')) {
             foreach ($row->attachments() as $attachment) {
                 if ($attachment->size() < 2097152) {
                     if ($attachment->isImage()) {
                         $file = basename($attachment->link('filepath'));
                         $html = preg_replace('/<a class="img" data\\-filename="' . str_replace('.', '\\.', $file) . '" href="(.*?)"\\>(.*?)<\\/a>/i', '<img src="' . $message->getEmbed($attachment->link('filepath')) . '" alt="" />', $html);
                     } else {
                         $message->addAttachment($attachment->link('filepath'));
                     }
                 }
             }
         }
         $message->addPart($html, 'text/html');
         // Loop through the addresses
         foreach ($defs as $def) {
             $def = trim($def);
             // Check if the address should come from Joomla config
             if ($def == '{config.mailfrom}') {
                 $def = Config::get('mailfrom');
             }
             // Check for a valid address
             if (Validate::email($def)) {
                 // Send e-mail
                 $message->setTo(array($def));
                 $message->send();
             }
         }
     }
     // Log activity
     $creator = User::getInstance($row->get('login'));
     if ($creator && $creator->get('id')) {
         Event::trigger('system.logActivity', ['activity' => ['action' => 'created', 'scope' => 'support.ticket', 'scope_id' => $row->get('id'), 'description' => Lang::txt('COM_SUPPORT_ACTIVITY_TICKET_CREATED', '<a href="' . Route::url($row->link()) . '">#' . $row->get('id') . ' - ' . $row->get('summary') . '</a>'), 'details' => array('id' => $row->get('id'), 'summary' => $row->get('summary'), 'url' => Route::url($row->link()))], 'recipients' => [['support.tickets', 1], ['user', $creator->get('id')]]]);
     }
     if (!User::isGuest() && $this->acl->check('update', 'tickets') > 0) {
         // Only do the following if a comment was posted
         // otherwise, we're only recording a changelog
         $old = new Ticket();
         $old->set('open', 1);
         $old->set('owner', 0);
         $old->set('status', 0);
         $old->set('tags', '');
         $old->set('severity', 'normal');
         $rowc = new Comment();
         $rowc->set('ticket', $row->get('id'));
         $rowc->set('created', Date::toSql());
         $rowc->set('created_by', User::get('id'));
         $rowc->set('access', 1);
         $rowc->set('comment', Lang::txt('COM_SUPPORT_TICKET_SUBMITTED'));
         // 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', ''));
         // Were there any changes, CCs, or comments to record?
         if (count($rowc->changelog()->get('changes')) > 0 || count($rowc->changelog()->get('cc')) > 0) {
             // Save the data
             if (!$rowc->store()) {
                 throw new Exception($rowc->getError(), 500);
             }
             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'));
             }
             $recipients = array(['support.tickets', 1]);
             // Check if the notify list has eny entries
             if (count($rowc->to())) {
                 $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;
                     }
                 }
                 $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']);
                 // Send e-mail to admin?
                 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'], $row->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']), $this->_option))) {
                         $this->setError(Lang::txt('COM_SUPPORT_ERROR_FAILED_TO_MESSAGE', $to['name'] . '(' . $to['role'] . ')'));
                     }
                     $rowc->changelog()->notified($to['role'], $to['name'], $to['email']);
                 }
                 foreach ($rowc->to('emails') as $to) {
                     if ($allowEmailResponses) {
                         $token = $encryptor->buildEmailToken(1, 1, -9999, $row->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
                         Utilities::sendEmail($email[0], $subject, $message, $from, $email[1]);
                     } else {
                         // email is just a plain 'ol string
                         Utilities::sendEmail($to['email'], $subject, $message, $from);
                     }
                     $rowc->changelog()->notified($to['role'], $to['name'], $to['email']);
                 }
             }
             // Were there any changes?
             if (count($rowc->changelog()->get('notifications')) > 0 || count($rowc->changelog()->get('cc')) > 0 || count($rowc->changelog()->get('changes')) > 0) {
                 // Save the data
                 if (!$rowc->store()) {
                     $this->setError($rowc->getError());
                 }
             }
             // Record the activity
             if (!$rowc->isPrivate() && $creator->get('id')) {
                 $recipients[] = ['user', $creator->get('id')];
             }
             $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]);
         }
     }
     // Trigger any events that need to be called
     Event::trigger('support.onTicketSubmission', array($row));
     // Output Thank You message
     $this->view->ticket = $row->get('id');
     $this->view->no_html = $no_html;
     foreach ($this->getErrors() as $error) {
         $this->view->setError($error);
     }
     $this->view->display();
 }