* @author Maxim Aisel * @license PHP License * @package WB * @subpackage content */ /** * Load classes */ WBClass::load('WBContent' , 'WBContent_ITS' , 'WBITS' , 'patI18n' ); /** * Content component: ITS_Ticket * * @version 1.3.0 * @package WB * @subpackage content */ class WBContent_ITS_Ticket extends WBContent_ITS { /** * Parameter list * * - captcha * - uploaddir * - action * - requiredgroup * - obscureid * - namespace * - titlebubbleformat * - titlebubblenotfound * - deadline: default deadline value or not set if empty parameter use strtotime() * - assigneduid: default user id to assign to, or 0 if empty * - owneruid: default user id for ticket owner, or 0 if empty * - status: default ticket status, if not empty * * @var array */ protected $config = array( 'captcha' => 'auto', 'uploaddir' => 0, 'action' => 'add', 'requiredgroup' => '', 'obscureid' => '', 'namespace' => '', 'titlebubbleformat' => 'Support Ticket: %s', 'titlebubblenotfound' => 'Support Ticket', 'deadline' => '', 'assigneduid' => '', 'owneruid' => '', 'status' => '' ); /** * Template Method Run * * Run component define algorithm, allow subclasses to implement runAction() * * @see runAction() * @return array parameter list */ final public function run() { unset($this->config['__path']); $this->tmpl->addGlobalVars($this->config, 'CONFIG_'); if (!$this->isUserInGroup($this->config['requiredgroup'])) { $this->loadTemplates('anon'); return $this->config; } $this->config['namespace'] = WBITS::selectNamespace($this->config['namespace']); $upload = 1; if (0 > $this->config['uploaddir']) { $upload = 0; } $this->tmpl->addGlobalVar('UPLOAD_ALLOWED', $upload); $this->runAction(); return $this->config; } /** * Separated Method to Switch Action * * Switch config['action'] and run proper functions */ protected function runAction() { switch ($this->config['action']) { case 'feedback': $this->saveFeedback(); $this->displayTickets(); break; case 'list': $this->listTicket(); break; case 'add': $this->processForm('edit', $this->req->export()); break; case 'upload': if(!$this->displayUpload()) { $this->displayTickets(); } break; case 'postlabel': if(!$this->displayPostLabel()) { $this->displayTickets(); } break; default: $this->displayTickets(); break; } } private function saveFeedback() { if (empty($this->req->get('save', ''))) { return; } $fb = trim(strip_tags($this->req->get('feedback', ''))); if (empty($fb)) { return; } $rating = $this->req->get('rating', 0); $rating = max(0, $rating); $rating = min(5, $rating); // cut off if (5000 < strlen($fb)) { $fb = substr($fb, 0, 5000); } $this->ticket = WBClass::create('WBITS_Ticket'); $this->ticket->loadByObscureId($this->config['obscureid']); $oid = $this->ticket->getObscureId(); if (empty($oid)) { return; } $data = $this->ticket->getData(); if (!empty($data['feedback'])) { return; } $save = array( 'feedback' => $fb, 'rating' => $rating ); $this->ticket->save($save); } /** * Upload * * @return bool */ private function displayUpload() { if (0 > $this->config['uploaddir']) { return false; } $this->ticket = WBClass::create('WBITS_Ticket'); $this->ticket->loadByObscureId($this->config['obscureid']); $oid = $this->ticket->getObscureId(); if (empty($oid)) { return false; } $this->processForm('upload', $this->ticket->getData()); return true; } /** * Postlabel * * @return bool * @todo Remove dependency to ValueAce_TeX! * @todo Use more general solution, depending on ticket scopes */ private function displayPostLabel() { $this->ticket = WBClass::create('WBITS_Ticket'); $this->ticket->loadByObscureId($this->config['obscureid']); $oid = $this->ticket->getObscureId(); if (empty($oid)) { return false; } $this->tex = WBClass::create('ValueAce_TeX_RMA'); $this->tex->setTicket($this->ticket); $pdf = $this->tex->render(); $this->downloadFile($pdf, 'application/pdf', 'ticket-' . $oid . '-shippingDocuments.pdf'); // this will never happen return true; } /** * List my tickets * * List tickets where this use account set as customer */ private function listTicket() { $pager = $this->its->getPager(WBITS::PAGER_TYPE_USER); $this->tmpl->addGlobalVars($pager->browse($this->config['goto']), 'pager_'); $this->loadTemplates('list'); $this->tmpl->addRows('list_entry', $pager->get()); } /** * Add Uploaded File to Ticket * * @param patForms $form * @param array $values */ protected function onUploadValid($form, $values) { $data = $this->ticket->getData(); if (!is_array($values['file'])) { $values['file'] = array($values['file']); } foreach ($values['file'] as $f) { $data['ticketmedia'][] = $f; } $save = array( 'ticketmedia' => $data['ticketmedia'] ); // save comment with file if (isset($values['filenote'])) { $save['comment'] = $values['filenote']; } $this->ticket->save($save); return true; } /** * Save ticket data * * Add new ticket * * @todo remove ticscopeid hack 4 postlabel * @param patForms $form * @param array $values * @return bool always true */ protected function onEditValid($form, $values) { if ($this->user->isAuthenticated()) { $values['customeruid'] = $this->user->getId(); } // remove captcha, if set if (isset($values['captcha'])) { unset($values['captcha']); } // generate title from blurb if (empty($values['title'])) { $blurb = $values['blurb']; $blurb = str_replace('

', "

\n", $blurb); $blurb = strip_tags($blurb); $blurb = str_replace(' ', ' ', $blurb); $blurb = trim($blurb); $blurb = array_map('trim', explode("\n", $blurb)); foreach ($blurb as $title) { $title = trim($title); if (5 > strlen($title)) { continue; } $values['title'] = $title; break; } } // set default deadline if (!empty($this->config['deadline'])){ $timestamp = strtotime($this->config['deadline']); $values['deadline'] = date('Y-m-d H:i:s', $timestamp); } // set more default values $dv = array( 'assigneduid', 'owneruid', 'status' ); foreach ($dv as $v) { if (empty($this->config[$v])) { continue; } $values[$v] = $this->config[$v]; } $this->addAttachment2Ticket($values); $params = array( 'namespace' => $this->config['namespace'] ); $this->ticket = WBClass::create('WBITS_Ticket', $params); $this->ticket->save($values); $this->tmpl->addGlobalVar('obscureid', $this->ticket->getObscureId()); $this->tmpl->addGlobalVars($values); switch ($values['ticscopeid']) { case 1: $this->tmpl->addGlobalVar('with_postlabel', 1); break; default: $this->tmpl->addGlobalVar('with_postlabel', 0); break; } return true; } /** * Add Uploaded File as Ticket Attachment * * @param array $values */ private function addAttachment2Ticket(&$values) { if (empty($this->config['uploaddir']) || !isset($values['file'])) { return; } $file = $values['file']; unset($values['file']); if (empty($file)) { return; } $tm = array(); /** @var WBVFS_File */ $vfs = WBClass::create('WBVFS_File'); $vfs->setCurrentDir($this->config['uploaddir'], true); $vfs = $vfs->import(WBParam::get('wb/dir/base') . '/var/tmp/file-upload/' . $file, $file); if ($vfs->isOK()) { $tm[] = $vfs->getId(); } $values['ticketmedia'] = $tm; } /** * List tickets * * Get pager and fill template with list * @todo check for configured namespace * @todo proper scope detection */ private function displayTickets() { $this->ticket = $this->its->loadByObscureId($this->config['obscureid']); $oid = $this->ticket->getObscureId(); if (empty($oid)) { $this->loadTemplates('notfound'); $this->bubbles['title'] = $this->config['titlebubblenotfound']; $this->setStatusCode(404); return; } $this->loadTemplates('display'); $data = $this->ticket->getData(); // check scope switch ($data['ticscopeid']) { case 1: $this->tmpl->addGlobalVar('with_postlabel', 1); break; default: $this->tmpl->addGlobalVar('with_postlabel', 0); break; } // check namespace $this->bubbles['title'] = sprintf($this->config['titlebubbleformat'], $data['title']); $tmplData = array(); foreach ($data as $key => $value) { if (is_scalar($value)) { $tmplData[$key] = $value; continue; } foreach($value as $k => $v) { if (is_scalar($v)) { $tmplData[$key . '_' . $k] = $v; } } } $this->tmpl->addGlobalVars($tmplData); $this->tmpl->addGlobalVar('obscureid', $oid); $this->tmpl->addGlobalVar('id', $this->ticket->getId()); } private function injectElement4Upload(&$list) { // upload file element if (empty($this->config['uploaddir'])) { return; } $dir = WBParam::get('wb/dir/base') . '/var/tmp/file-%s'; if (!is_dir(sprintf($dir, 'upload'))) { mkdir(sprintf($dir, 'upload'), 0777, true); chmod(sprintf($dir, 'upload'), 0777); } if (!is_dir(sprintf($dir, 'tmp'))) { mkdir(sprintf($dir, 'tmp'), 0777, true); chmod(sprintf($dir, 'tmp'), 0777); } $list['file'] = array( 'type' => 'File', 'attributes' => array( 'required' => 'no', 'title' => patI18n::dgettext('wombat', 'Upload'), 'label' => patI18n::dgettext('wombat', 'Upload'), 'description' => patI18n::dgettext('wombat', 'Upload ticket attachment (screenshot, log file, ..)'), 'class' => 'form-control', 'uploaddir' => sprintf($dir, 'upload'), 'tempdir' => sprintf($dir, 'tmp'), 'overwrite' => 'yes', 'usesession' => 'yes', 'permissions' => '0666', 'onchange' => 'new WB.Form.Element.File(this).update();' ) ); } /** * Fetch list of form elements * * Use different file regardless of actual form name. * * @param string name of form * @return array $elements */ protected function getFormElementList($name) { $list = parent::getFormElementList($name); if (!in_array($name, array('edit', 'upload'))) { return $list; } $this->injectElement4Captcha($list, $this->user->isAuthenticated(), $this->config['captcha']); if ('edit' != $name) { return $list; } // use config as defaults $invalid = array( 'captcha', 'uploaddir', 'action', 'requiredgroup', 'obscureid', 'namespace', 'titlebubbleformat', 'titlebubblenotfound' ); foreach ($this->config as $k => $v) { // does form element with that name exist? if (!isset($list[$k])) { continue; } // don't allow to copy everything, even if form element does exists if (in_array($k, $invalid)) { continue; } $list[$k]['attributes']['default'] = $v; } $this->injectElement4Upload($list); // copy default values from user data if ($this->user->isAuthenticated()) { $userData = $this->user->getData(); // name if (isset($list['customername'])) { $list['customername']['attributes']['default'] = $userData['forename'] . ' ' . $userData['surname']; } // e-mail if (isset($list['customeremailurlid'])) { $list['customeremailurlid']['attributes']['default'] = $userData['email']; } if (isset($list['emailurlid'])) { $list['emailurlid']['attributes']['default'] = $userData['email']; } // generic copy of user data if form element's name starts with "customer" foreach ($list as $key => &$value) { // those fields are done before if (in_array($key, array('customername', 'customeremailurlid', 'emailurlid', 'title', 'blurb'))) { continue; } if (0 == strncmp($key, 'customer', 8)) { $suffix = substr($key, 8); if (isset($userData[$suffix])) { $value['attributes']['default'] = $userData[$suffix]; } continue; } if (isset($userData[$key])) { $value['attributes']['default'] = $userData[$key]; } } } return $list; } }