v7‰PNG
IHDR Ÿ f Õ†C1 sRGB ®Îé gAMA ±üa pHYs à ÃÇo¨d GIDATx^íÜL”÷ð÷Yçªö("Bh_ò«®¸¢§q5kÖ*:þ0AºšÖ¥]VkJ¢M»¶f¸±8\k2íll£1]q®ÙÔ‚ÆT
PK \*
helpdesk/db.xmlnu [
PK \W֨ $ helpdesk/library/HelpdeskMessage.phpnu [ _ticket)) {
$this->_ticket = $this->getDi()->helpdeskTicketTable->load($this->ticket_id);
}
return $this->_ticket;
}
public function setAttachments($attachments)
{
$this->attachments = $this->serializeIds($attachments);
}
public function getAttachments()
{
return $this->unserializeIds($this->attachments);
}
public function loadGetAttachments()
{
if (is_null($this->_attachments))
$this->_attachments = $this->getDi()->uploadTable->loadIds($this->getAttachments());
return $this->_attachments;
}
public function delete()
{
foreach ($this->loadGetAttachments() as $att) {
/* @var $att Upload */
if ($att->prefix == Bootstrap_Helpdesk::ATTACHMENT_UPLOAD_PREFIX)
$att->delete();
}
parent::delete();
}
}
class HelpdeskMessageTable extends Am_Table
{
protected $_key = 'message_id';
protected $_table = '?_helpdesk_message';
protected $_recordClass = 'HelpdeskMessage';
public function insert(array $values, $returnInserted = false)
{
if (empty($values['dattm']))
$values['dattm'] = $this->getDi()->sqlDateTime;
return parent::insert($values, $returnInserted);
}
function selectLast($num)
{
return $this->selectObjects("SELECT m.*,
u.user_id, u.name_f AS u_name_f, u.name_l AS u_name_l, u.login AS u_login, u.email AS u_email,
a.admin_id, a.name_f AS a_name_f, a.name_l AS a_name_l, a.login AS a_login, a.email AS a_email,
t.ticket_mask as ticket_mask, t.subject as subject
FROM ?_helpdesk_message m LEFT JOIN ?_helpdesk_ticket t USING (ticket_id)
LEFT JOIN ?_user u ON t.user_id = u.user_id
LEFT JOIN ?_admin a ON m.admin_id = a.admin_id
ORDER BY m.dattm DESC LIMIT ?d", $num);
}
}PK \wg g % helpdesk/library/HelpdeskCategory.phpnu [ getTable()->getName();
$max = $this->getAdapter()->selectCell("SELECT MAX(sort_order) FROM {$table_name}");
$this->sort_order = $max + 1;
return parent::insert($reload);
}
public function delete()
{
$ret = parent::delete();
$table_name = $this->getTable()->getName();
$this->getAdapter()->query("UPDATE {$table_name}
SET sort_order=sort_order-1
WHERE sort_order>?", $this->sort_order);
return $ret;
}
}
class HelpdeskCategoryTable extends Am_Table
{
protected $_key = 'category_id';
protected $_table = '?_helpdesk_category';
protected $_recordClass = 'HelpdeskCategory';
function getOptions($include_disabled=false)
{
return $this->getAdapter()->selectCol("SELECT category_id AS ARRAY_KEY, title
FROM ?_helpdesk_category
WHERE 1 {AND is_disabled=?}
ORDER BY sort_order",
$include_disabled ? DBSIMPLE_SKIP : 0);
}
}PK \62 helpdesk/library/HelpdeskFaq.phpnu [ getTable()->getName();
$max = $this->getAdapter()->selectCell("SELECT MAX(sort_order) FROM {$table_name}");
$this->sort_order = $max + 1;
return parent::insert($reload);
}
public function delete()
{
$ret = parent::delete();
$table_name = $this->getTable()->getName();
$this->getAdapter()->query("UPDATE {$table_name}
SET sort_order=sort_order-1
WHERE sort_order>?", $this->sort_order);
return $ret;
}
}
class HelpdeskFaqTable extends Am_Table
{
protected $_key = 'faq_id';
protected $_table = '?_helpdesk_faq';
protected $_recordClass = 'HelpdeskFaq';
function getCategories()
{
return $this->_db->selectCol("SELECT DISTINCT category, category AS ?
FROM ?_helpdesk_faq
WHERE category IS NOT NULL
ORDER BY category", DBSIMPLE_ARRAY_KEY);
}
}
PK \rN&2 ' helpdesk/library/Am/Report/Helpdesk.phpnu [ title = ___('Count of User Messages in Helpdesk');
}
public function getPointField()
{
return 'hm.dattm';
}
/** @return Am_Query */
public function getQuery()
{
$q = new Am_Query($this->getDi()->helpdeskMessageTable, 'hm');
$q->clearFields();
$q->addField('COUNT(message_id)', 'cnt');
$q->addWhere('admin_id IS NULL');
return $q;
}
function getLines()
{
$ret = array();
$ret[] = new Am_Report_Line('cnt', ___('Count of Messages'));
return $ret;
}
}PK \b! 4 helpdesk/library/Am/Helpdesk/Strategy/Admin/User.phpnu [ getDi()->router;;
return $router->assemble(array(
'module' => 'helpdesk',
'controller' => $this->getControllerName(),
'user_id' => $this->getUserId()
) + $params, $route, true);
}
public function setUserId($user_id)
{
$this->user_id = $user_id;
}
public function getUserId()
{
return $this->user_id;
}
public function createNewTicketForm()
{
$form = parent::createNewTicketForm();
$user = $this->getDi()->userTable->load($this->getUserId());
$text = HTML_QuickForm2_Factory::createElement('html', 'loginOrEmail');
$text->setLabel(___('User'))
->setHtml(sprintf('
%s %s (%s)
',
$user->name_f,
$user->name_l,
$user->login
));
$text->toggleFrozen(true);
$form->insertBefore($text, $form->getElementById('loginOrEmail'));
$form->removeChild(
$form->getElementById('loginOrEmail')
);
$loginOrEmail = HTML_QuickForm2_Factory::createElement('hidden', 'loginOrEmail');
$loginOrEmail->setValue($user->login);
$form->addElement($loginOrEmail);
$user_id = HTML_QuickForm2_Factory::createElement('hidden', 'user_id');
$user_id->setValue($user->pk());
$form->addElement($user_id);
return $form;
}
}
PK \YT . helpdesk/library/Am/Helpdesk/Strategy/User.phpnu [ _identity = $user_id ? $user_id : $this->getDi()->auth->getUserId();
}
public function isMessageAvalable($message)
{
return!($message->type == 'comment' && $message->admin_id);
}
public function isMessageForReply($message)
{
if ($message->type == 'comment') {
return false;
} else {
return (boolean) $message->admin_id;
}
}
public function fillUpMessageIdentity($message)
{
return $message;
}
public function fillUpTicketIdentity($ticket, $request)
{
$ticket->user_id = $this->getIdentity();
return $ticket;
}
public function getTicketStatusAfterReply($message)
{
if ($message->type == 'comment') {
return $message->getTicket()->status;
} else {
return 'awaiting_admin_response';
}
}
public function onAfterInsertMessage($message, $ticket)
{
if ($this->getDi()->config->get('helpdesk.notify_new_message_admin', 1)) {
$user = $this->getUser($message->getTicket()->user_id);
$recepients[] = Am_Mail_Template::TO_ADMIN;
$exists = array($this->getDi()->config->get('admin_email') => 1);
if (($owner = $message->getTicket()->getOwner()) && !isset($exists[$owner->email])) {
$recepients[] = $owner;
$exists[$owner->email] = 1;
}
foreach ($message->getTicket()->getWatchers() as $w) {
if (!isset($exists[$w->email])) {
$recepients[] = $w;
$exists[$w->email] = 1;
}
}
foreach ($recepients as $recepient) {
if ($et = Am_Mail_Template::load('helpdesk.notify_new_message_admin')) {
$et->setTicket($message->getTicket());
$et->setUser($user);
$et->setMessage($message);
$et->setUrl($this->getDi()->url('helpdesk/admin/ticket/'.$message->getTicket()->ticket_mask,null,false,true));
$et->send($recepient);
}
}
}
}
public function onAfterInsertTicket($ticket)
{
if ($this->getDi()->config->get('helpdesk.new_ticket')) {
$user = $this->getUser($ticket->user_id);
if ($user->unsubscribed)
return;
$et = Am_Mail_Template::load('helpdesk.new_ticket', $user->lang);
if ($et) {
$et->setTicket($ticket);
$et->setUser($user);
$et->setUrl(sprintf('%s/helpdesk/ticket/%s',
$this->getDi()->config->get('root_surl'),
$ticket->ticket_mask)
);
$et->send($user);
}
}
}
public function onViewTicket($ticket)
{
if ($ticket->has_new) {
$ticket->updateQuick('has_new', 0);
}
}
public function getAdminName($message)
{
if ($this->getDi()->modules->get('helpdesk')->getConfig('disclosure_admin')) {
$admin = $this->getAdmin($message->admin_id);
return $admin ? $admin->getName() : ___('Administrator');
} else {
return ___('Administrator');
}
}
public function getTemplatePath()
{
return 'helpdesk';
}
public function getIdentity()
{
return $this->_identity;
}
public function canViewTicket($ticket)
{
return $ticket->user_id == $this->getIdentity();
}
public function canViewMessage($message)
{
return $message->getTicket()->user_id == $this->getIdentity();
}
public function canEditTicket($ticket)
{
return $ticket->user_id == $this->getIdentity() &&
$ticket->status != HelpdeskTicket::STATUS_CLOSED;
}
public function canEditMessage($message)
{
return $message->type == 'comment' &&
($message->getTicket()->user_id == $this->getIdentity());
}
public function canUseSnippets()
{
return false;
}
public function canUseFaq()
{
return false;
}
public function canEditOwner($ticket)
{
return false;
}
public function canEditWatcher($ticket)
{
return false;
}
public function canViewOwner($ticket)
{
return false;
}
public function canEditCategory($ticket)
{
return false;
}
public function createForm()
{
$form = new Am_Form();
$form->addCsrf();
$form->setAttribute('class', 'am-helpdesk-form');
return $form;
}
function getCategoryOptions()
{
$op = $this->getDi()->helpdeskCategoryTable->getOptions();
$user = $this->getUser($this->getIdentity());
foreach (array_keys($op) as $id) {
if (!$this->getDi()->resourceAccessTable->userHasAccess($user, $id, HelpdeskCategory::ACCESS_TYPE)) {
unset($op[$id]);
}
}
return $op;
}
public function createNewTicketForm()
{
$form = parent::createNewTicketForm();
if ($this->getDi()->helpdeskFaqTable->countBy()) {
$id = $form->getId();
$s_url = json_encode($this->getDi()->url('helpdesk/faq/suggest',null,false));
$form->addScript()->setScript(<<');
}
jQuery("#am-helpdesk-faq-q-result").empty();
return;
}
jQuery.get($s_url, {q:jQuery(this).val()}, function(html){
jQuery("#am-helpdesk-faq-q-result").empty().append(html);
})
return false;
});
CUT
);
}
return $form;
}
public function addUpload($form)
{
if (!$this->getDi()->modules->get('helpdesk')->getConfig('does_not_allow_attachments')) {
$t = Am_Html::escape(___('Add Attachments'));
$form->addHtml()->setHtml(<<$t
CUT
);
$form->addUpload('attachments', array('multiple' => 1), array('prefix' => Bootstrap_Helpdesk::ATTACHMENT_UPLOAD_PREFIX, 'secure' => true))
->setLabel(___('Attachments'))
->setJsOptions(<<assembleUrl(array(
'ticket' => $ticket->ticket_mask
), 'helpdesk-ticket');
}
public function newUrl()
{
return $this->assembleUrl(array(), 'helpdesk-new');
}
protected function getControllerName()
{
return 'index';
}
}PK \vxZ Z 2 helpdesk/library/Am/Helpdesk/Strategy/Abstract.phpnu [ _di = $di;
}
/**
* @return Am_Di
*/
protected function getDi()
{
return $this->_di;
}
function onAfterInsertTicket($ticket)
{
}
public function assembleUrl($params, $route = 'default')
{
$router = $this->getDi()->router;;
return $router->assemble(array(
'module' => 'helpdesk',
'controller' => $this->getControllerName(),
) + $params, $route, true);
}
abstract public function ticketUrl($ticket);
abstract public function newUrl();
/**
* @return Am_Helpdesk_Strategy_Abstract
*/
public static function create(Am_Di $di)
{
return defined('AM_ADMIN') ?
($di->request->getControllerName() == 'admin-user' ?
new Am_Helpdesk_Strategy_Admin_User($di) :
new Am_Helpdesk_Strategy_Admin($di) ) :
new Am_Helpdesk_Strategy_User($di);
}
function getCategoryOptions()
{
return $this->getDi()->helpdeskCategoryTable->getOptions();
}
/**
* @return Am_Form
*/
public function createNewTicketForm()
{
$form = $this->createForm();
if ($options = $this->getCategoryOptions()) {
$form->addAdvradio('category_id')
->setLabel(___('Category of question'))
->loadOptions($options)
->addRule('required');
$fields = $this->getDi()->helpdeskTicketTable->customFields()->getAll();
foreach ($this->getDi()->helpdeskCategoryTable->findByIsDisabled(0) as $c) {
foreach (Am_Record::unserializeList($c->fields) as $fn) {
if (isset($fields[$fn])) {
$fields[$fn]->name = sprintf('category[%d][%s]',
$c->pk(), $_ = $fields[$fn]->name);
$fields[$fn]->addToQF2($form, array(), array(), HTML_QuickForm2_Rule::ONBLUR_CLIENT);
$fields[$fn]->name = $_;
}
}
}
$form->addScript()
->setScript(<<getDi()->helpdeskTicketTable->customFields()->getAll()) {
foreach ($fields as $field) {
$field->name = sprintf('additional[%s]', $_ = $field->name);
$field->addToQF2($form, array(), array(), HTML_QuickForm2_Rule::ONBLUR_CLIENT);
$field->name = $_;
}
}
$subject = $form->addText('subject', array('class' => 'row-wide el-wide'))
->setLabel(___('Subject'));
$subject->addRule('required');
$subject->addRule('maxlength', ___('Your subject is too verbose'), 255);
$subject->addRule('nonempty', ___('Subject can not be empty'));
$content = $form->addTextarea('content', array('class' => 'row-wide el-wide', 'rows' => 12))
->setLabel(___('Message'));
$content->addRule('required');
$content->addRule('nonempty', ___('Message can not be empty'));
$this->addUpload($form);
return $form;
}
function isShowAvatar()
{
return $this->getDi()->modules->get('helpdesk')->getConfig('show_gravatar') ||
($this->getDi()->plugins_misc->isEnabled('avatar') &&
$this->getDi()->modules->get('helpdesk')->getConfig('show_avatar'));
}
public function getAvatar($message)
{
if ($this->getDi()->plugins_misc->isEnabled('avatar') &&
$this->getDi()->modules->get('helpdesk')->getConfig('show_avatar')) {
if ($message->admin_id) {
return $this->getAdminAvatar($message);
} else {
return $this->getUserAvatar($message);
}
} elseif ($this->getDi()->modules->get('helpdesk')->getConfig('show_gravatar')) {
if ($message->admin_id) {
return $this->getAdminGravatar($message);
} else {
return $this->getUserGravatar($message);
}
} else {
return '';
}
}
public function getAdminGravatar($message)
{
$admin = $this->getAdmin($message->admin_id);
return $admin ?
sprintf(' ',
'//www.gravatar.com/avatar/' . md5(strtolower(trim($admin->email))) . '?s=40&d=mm') :
'';
}
public function getUserGravatar($message)
{
$user = $this->getUser($message->getTicket()->user_id);
return $user ?
sprintf(' ',
'//www.gravatar.com/avatar/' . md5(strtolower(trim($user->email))) . '?s=40&d=mm') :
'';
}
public function getAdminAvatar($message)
{
$admin = $this->getAdmin($message->admin_id);
return $admin ?
sprintf(' ',
$this->getDi()->url('misc/avatar/' . $admin->avatar)) :
'';
}
public function getUserAvatar($message)
{
$user = $this->getUser($message->getTicket()->user_id);
return $user ?
sprintf(' ',
$this->getDi()->url('misc/avatar/' . $user->avatar)) :
'';
}
public function getName($message)
{
return $message->admin_id ?
$this->getAdminName($message) :
$this->getUserName($message);
}
public function getUserName($message)
{
$user = $this->getUser($message->getTicket()->user_id);
$name = trim("{$user->name_f} {$user->name_l}");
return sprintf('%s%s',
$user->login,
$name ? sprintf(' (%s)', $name) : ''
);
}
protected function getAdmin($admin_id)
{
return $this->getDi()->adminTable->load($admin_id, false);
}
protected function getUser($user_id)
{
return $this->getDi()->userTable->load($user_id);
}
}PK \| / helpdesk/library/Am/Helpdesk/Strategy/Admin.phpnu [ type == 'comment' && !$message->admin_id);
}
public function isMessageForReply($message)
{
if ($message->type == 'comment') {
return false;
} else {
return!$message->admin_id;
}
}
public function fillUpMessageIdentity($message)
{
$message->admin_id = $this->getIdentity();
return $message;
}
public function fillUpTicketIdentity($ticket, $request)
{
//loginOrEmail was already validated in form
//and we must find user with such login or email
//in any case
$user = $this->getDi()->userTable->findFirstByLogin($request->get('loginOrEmail'));
if (!$user) {
$user = $this->getDi()->userTable->findFirstByEmail($request->get('loginOrEmail'));
}
$ticket->user_id = $user->user_id;
return $ticket;
}
public function getTicketStatusAfterReply($message)
{
if ($message->type == 'comment') {
return $message->getTicket()->status;
} else {
return 'awaiting_user_response';
}
}
public function onAfterInsertMessage($message, $ticket)
{
if ($message->type == 'message') {
$ticket->updateQuick('has_new', 1);
}
if ($message->type == 'message'
&& $this->getDi()->config->get('helpdesk.notify_new_message', 1)) {
$user = $this->getUser($message->getTicket()->user_id);
if ($user->unsubscribed)
return;
$et = Am_Mail_Template::load('helpdesk.notify_new_message', $user->lang);
if ($et) {
$et->setTicket($message->getTicket());
$et->setUser($user);
$et->setMessage($message);
$et->setUrl($this->getDi()->url('helpdesk/ticket/'.$message->getTicket()->ticket_mask,null,false,true));
$et->send($user);
}
}
}
public function onViewTicket($ticket)
{
//nop
}
/**
* @return Am_Form
*/
public function createNewTicketForm()
{
$form = parent::createNewTicketForm();
$element = HTML_QuickForm2_Factory::createElement('text', 'loginOrEmail');
$element->setId('loginOrEmail')
->setLabel(___('Username/Email'))
->addRule('callback', ___('Can not find user with such username or email'), array($this, 'checkUser'));
//prepend element to form
$formElements = $form->getElements();
$form->insertBefore($element, $formElements[0]);
$from = HTML_QuickForm2_Factory::createElement('select', 'from');
$from->setLabel(___('Create ticket as'));
$from->loadOptions(array(
'admin' => ___('Admin'),
'user' => ___('Customer')
));
$form->insertBefore($from, $element);
$form->addScript('script')->setScript(<<getId();
$snippets = ___('Snippets');
$form->addScript('snippets')->setScript(<<$snippets ')
jQuery('#snippets-link').bind('click', function(){
var \$this = jQuery(this);
var div = jQuery('
');
div.load(amUrl('/helpdesk/admin/p/view/displaysnippets'), {}, function(){
div.dialog({
autoOpen: true,
modal : true,
title : "",
width : 700,
position : ['center', 'center']
});
div.find('.grid-wrap').bind('load', function() {
jQuery(this).find('a.am-helpdesk-insert-snippet').unbind().click(function(){
var \$target = \$this.closest('div.am-form').find('textarea[name=content]');
\$target.insertAtCaret(jQuery(this).data('snippet-content'))
div.dialog('close');
})
})
})
})
CUT
);
return $form;
}
public function addUpload($form)
{
$t = Am_Html::escape(___('Add Attachments'));
$form->addHtml()->setHtml(<<$t
CUT
);
$form->addUpload('attachments', array('multiple' => 1), array('prefix' => Bootstrap_Helpdesk::ADMIN_ATTACHMENT_UPLOAD_PREFIX, 'secure' => true))
->setLabel(___('Attachments'));
}
public function getAdminName($message)
{
$admin = $this->getAdmin($message->admin_id);
return $admin ? $admin->login : ___('Administrator has been removed, id [%d]', $message->admin_id);
}
public function getTemplatePath()
{
return 'admin/helpdesk';
}
public function getIdentity()
{
$admin = $this->getDi()->authAdmin->getUser();
return $admin->pk();
}
public function canViewTicket($ticket)
{
return true;
}
public function canViewMessage($message)
{
return true;
}
public function canEditTicket($ticket)
{
return true;
}
public function canEditMessage($message)
{
return ($message->type == 'comment' && (boolean) $message->admin_id) ||
($this->getDi()->modules->get('helpdesk')->getConfig('can_edit') &&
$message->admin_id &&
$this->getDi()->authAdmin->getUserId() == $message->admin_id &&
$message->dattm > sqlTime('-5 minute')
);
}
public function canUseSnippets()
{
return true;
}
public function canUseFaq()
{
return true;
}
public function canEditOwner($ticket)
{
return true;
}
public function canEditWatcher($ticket)
{
return true;
}
public function canViewOwner($ticket)
{
return true;
}
public function canEditCategory($ticket)
{
return true;
}
public function checkUser($loginOrEmail)
{
$user = $this->getDi()->userTable->findFirstByLogin($loginOrEmail);
if (!$user) {
$user = $this->getDi()->userTable->findFirstByEmail($loginOrEmail);
}
return (boolean) $user;
}
public function createForm()
{
$form = new Am_Form_Admin();
$form->setAttribute('class', 'am-helpdesk-form');
return $form;
}
public function ticketUrl($ticket)
{
return $this->assembleUrl(array(
'ticket' => $ticket->ticket_mask
), 'helpdesk-ticket-admin');
}
public function newUrl()
{
return $this->assembleUrl(array(), 'helpdesk-new-admin');
}
protected function getControllerName()
{
return 'admin';
}
}PK \ެLcY cY + helpdesk/library/Am/Helpdesk/Controller.phpnu [ hasPermission(Bootstrap_Helpdesk::ADMIN_PERM_ID);
}
public function init()
{
$this->strategy = $this->getDi()->helpdeskStrategy;
$type = defined('AM_ADMIN') ? 'admin' : 'user';
$this->getView()->headLink()->appendStylesheet($this->getView()->_scriptCss('helpdesk-' . $type . '.css'));
$this->getView()->registerHelper(new Am_View_Helper_HelpdeskGetTicketField($this->getDi()->helpdeskTicketTable->customFields()->getAll()), 'helpdeskGetTicketField');
parent::init();
}
protected function isGridRequest($gridId)
{
foreach ($this->getRequest()->getParams() as $key => $val)
if (substr($key, 0, strlen($gridId)) == $gridId)
return true;
return false;
}
public function newAction()
{
if (!$this->getModule()->getConfig('live')) return;
Zend_Session::writeClose();
set_time_limit(0);
while (@ob_end_clean());
$message = $this->getDi()->helpdeskMessageTable->load($this->getDi()->security->reveal($this->getParam('id')));
if (!$this->strategy->canViewMessage($message)) {
throw new Am_Exception_AccessDenied(___('Access Denied'));
}
$ticket = $message->getTicket();
if (!$this->strategy->canViewTicket($ticket)) {
throw new Am_Exception_AccessDenied(___('Access Denied'));
}
while (!($messages = $this->getDi()->helpdeskMessageTable->selectObjects("SELECT * " .
"FROM ?_helpdesk_message WHERE ticket_id=? AND message_id>? ORDER BY message_id DESC",
$ticket->pk(), $message->pk()
))) {
sleep(2);
}
$this->strategy->onViewTicket($ticket);
$out = '';
$message_id = null;
$this->view->strategy = $this->strategy;
$this->view->ticket = $ticket;
foreach ($messages as $message) {
$message_id = $message_id ?: $message->pk();
$this->view->message = $message;
$out .= $this->view->render($this->strategy->getTemplatePath() . '/_message.phtml');
}
$url = json_encode($this->strategy->newUrl(). '?' . http_build_query(array(
'id' => $this->getDi()->security->obfuscate($message_id))));
$html = json_encode($out);
echo <<getDi()->helpdeskMessageTable->load($this->getDi()->security->reveal($this->getParam('message_id')));
if (!$this->strategy->canViewMessage($message)) {
throw new Am_Exception_AccessDenied(___('Access Denied'));
}
$upload = $this->getDi()->uploadTable->load($this->getDi()->security->reveal($this->getParam('id')));
if (!in_array($upload->pk(), $message->getAttachments())) {
throw new Am_Exception_AccessDenied(___('Access Denied'));
}
if (!in_array($upload->prefix, array(
Bootstrap_Helpdesk::ATTACHMENT_UPLOAD_PREFIX,
Bootstrap_Helpdesk::ADMIN_ATTACHMENT_UPLOAD_PREFIX))) {
throw new Am_Exception_AccessDenied(___('Access Denied'));
}
$this->_helper->sendFile($upload->getFullPath(), $upload->mime, array(
'filename' => $upload->getName()
));
}
public function surrenderAction()
{
$ticketIdentity = $this->getParam('ticket');
$ticket = $this->getDi()->helpdeskTicketTable->load($ticketIdentity);
if (!$this->strategy->canEditOwner($ticket)) {
throw new Am_Exception_AccessDenied(___('Access Denied'));
}
if ($ticket->owner_id == $this->strategy->getIdentity()) {
$ticket->owner_id = null;
$ticket->save();
}
$this->redirectTicket($ticket);
}
public function takeAction()
{
$ticketIdentity = $this->getParam('ticket');
$ticket = $this->getDi()->helpdeskTicketTable->load($ticketIdentity);
if (!$this->strategy->canEditOwner($ticket)) {
throw new Am_Exception_AccessDenied(___('Access Denied'));
}
$id = $this->getParam('id');
$id = $id ? $this->getDi()->security->reveal($id) : $this->strategy->getIdentity();
$ticket->owner_id = $id;
$ticket->save();
if (($this->strategy->getIdentity() != $id) &&
$this->getModule()->getConfig('notify_assign')) {
$admin = $this->getDi()->adminTable->load($id);
$et = Am_Mail_Template::load('helpdesk.notify_assign');
$et->setTicket($ticket);
$et->setAdmin($admin);
$et->setUrl($this->getDi()->url('helpdesk/admin/ticket/'.$ticket->ticket_mask,null,false,2));
$et->send($admin->email);
}
$this->redirectTicket($ticket);
}
public function editcategoryAction()
{
$ticketIdentity = $this->getParam('ticket');
$ticket = $this->getDi()->helpdeskTicketTable->load($ticketIdentity);
if (!$this->strategy->canEditCategory($ticket)) {
throw new Am_Exception_AccessDenied(___('Access Denied'));
}
$ticket->category_id = $this->getDi()->security->reveal($this->getParam('id'));
$ticket->save();
$this->redirectTicket($ticket);
}
public function lockAction()
{
if (defined('AM_ADMIN') && AM_ADMIN) {
$ticketIdentity = $this->getParam('ticket');
/* @var $ticket HelpdeskTicket */
$ticket = $this->getDi()->helpdeskTicketTable->load($ticketIdentity);
$ticket->lock($this->getDi()->authAdmin->getUser());
}
}
public function viewAction()
{
$ticketIdentity = $this->getParam('ticket');
$ticket = $this->getDi()->helpdeskTicketTable->load($ticketIdentity);
if (!$this->strategy->canViewTicket($ticket)) {
throw new Am_Exception_AccessDenied(___('Access Denied'));
}
$this->strategy->onViewTicket($ticket);
$grid = new Am_Helpdesk_Grid_Admin($this->getRequest(), $this->getView());
$grid->getDataSource()->getDataSourceQuery()->addWhere('m.user_id=?d', $ticket->user_id);
$grid->actionsClear();
$grid->removeField('m_login');
$grid->removeField('avatar');
$grid->removeField('gravatar');
$grid->addCallback(Am_Grid_ReadOnly::CB_TR_ATTRIBS, function(& $ret, $record) use ($ticket) {
if ($record->pk() == $ticket->pk())
$ret['class'] = isset($ret['class']) ? $ret['class'] . ' emphase' : 'emphase';
});
if ($this->getDi()->helpdeskTicketTable->countByUserId($ticket->user_id) < 10) {
$grid->addCallback(Am_Grid_ReadOnly::CB_RENDER_CONTENT, function(&$out, $g){
$out = preg_replace('/.*?/is', '', $out);
});
$grid->addCallback(Am_Grid_ReadOnly::CB_RENDER_TITLE, function(&$out, $g){
$out = '';
});
}
$grid->isAjax($this->isAjax() && $this->isGridRequest('_admin'));
if ($grid->isAjax()) {
echo $grid->run();
return;
}
$category = $ticket->getCategory();
$t = $this->getView();
$t->assign('ticket', $ticket);
$t->assign('category', $category);
$t->assign('user', $ticket->getUser());
$t->assign('strategy', $this->strategy);
$t->assign('historyGrid', $grid->render());
$t->assign('customFields', $this->getDi()->helpdeskTicketTable->customFields()->getAll());
$content = $t->render($this->strategy->getTemplatePath() . '/ticket.phtml');
if ($this->_request->isXmlHttpRequest()) {
header('Content-type: text/html; charset=UTF-8');
echo $content;
} else {
$this->view->assign('content', $content);
$this->view->display($this->strategy->getTemplatePath() . '/index.phtml');
}
}
public function replyAction()
{
$ticket = $this->getDi()->helpdeskTicketTable->load($this->getParam('ticket'));
if (!$this->strategy->canEditTicket($ticket)) {
throw new Am_Exception_AccessDenied(___('Access Denied'));
}
$message = null;
$type = $this->getParam('type', 'message');
if ($message_id = $this->getDi()->security->reveal($this->getParam('message_id'))) {
$message = $this->getDi()->helpdeskMessageTable->load($message_id);
switch ($type) {
case 'message' :
if (!$this->strategy->canViewMessage($message)) {
throw new Am_Exception_AccessDenied(___('Access Denied'));
}
break;
case 'comment' :
if (!$this->strategy->canEditMessage($message)) {
throw new Am_Exception_AccessDenied(___('Access Denied'));
}
break;
default :
throw new Am_Exception_InputError('Unknown message type : ' . $type);
}
}
/* @var $replyForm Am_Form */
$replyForm = $this->getReplyForm(
$this->getParam('ticket'),
$message,
$type
);
if ($this->isPost()) {
$replyForm->setDataSources(array($this->getRequest()));
$values = $replyForm->getValue();
$message_id = $this->getParam('message_id', null);
$message_id = $message_id ? $this->getDi()->security->reveal($message_id) : $message_id;
$this->reply($ticket, $message_id, $values);
$this->getRequest()->set('ticket', $ticket->ticket_mask);
if ($this->_request->isXmlHttpRequest()) {
return;
} else {
return $this->redirectTicket($ticket);
}
}
$content = (string) $replyForm;
if ($this->_request->isXmlHttpRequest()) {
header('Content-type: text/html; charset=UTF-8');
echo $content;
} else {
$this->view->assign('content', $content);
$this->view->display($this->strategy->getTemplatePath() . '/index.phtml');
}
}
public function changestatusAction()
{
$ticketIdentity = $this->getParam('ticket');
$ticket = $this->getDi()->helpdeskTicketTable->load($ticketIdentity);
if (!$this->strategy->canEditTicket($ticket)) {
throw new Am_Exception_AccessDenied(___('Access Denied'));
}
$ticket->status = $this->getParam('status');
$ticket->save();
return $this->redirectTicket($ticket);
}
public function displaysnippetsAction()
{
if (!$this->strategy->canUseSnippets()) {
throw new Am_Exception_AccessDenied();
}
$ticket = $this->getDi()->helpdeskTicketTable->load($this->getParam('ticket'), false);
$tpl = null;
if ($ticket) {
$tpl = new Am_SimpleTemplate;
$tpl->assign('user', $ticket->getUser());
}
$ds = new Am_Query($this->getDi()->helpdeskSnippetTable);
$grid = new Am_Grid_Editable('_snippet', ___('Snippets'), $ds, $this->getRequest(), $this->view, $this->getDi());
$grid->addField('title', ___('Title'))->setRenderFunction(
function ($record, $fieldName, $grid) use ($tpl) {
$c = $record->content;
if ($tpl) {
$c = $tpl->render($c);
}
return sprintf('%s ',
Am_Html::escape($c),
Am_Html::escape($record->title));
});
$grid->setForm(array($this, 'createForm'));
$grid->actionGet('insert')->setTarget(null);
$grid->setPermissionId(Bootstrap_Helpdesk::ADMIN_PERM_ID);
$grid->isAjax($this->isAjax() && $this->isGridRequest('_snippet'));
echo $grid->run();
}
public function displayfaqAction()
{
if (!$this->strategy->canUseFaq()) {
throw new Am_Exception_AccessDenied();
}
$ds = new Am_Query($this->getDi()->helpdeskFaqTable);
$grid = new Am_Grid_ReadOnly('_helpdesk_faq', ___('FAQ'), $ds, $this->getRequest(), $this->view, $this->getDi());
$grid->addField('title', ___('Title'))->setRenderFunction(array($this, 'renderFaqTitle'));
$grid->addField('category', ___('Category'));
$grid->setPermissionId(Bootstrap_Helpdesk::ADMIN_PERM_ID);
$grid->isAjax($this->isAjax() && $this->isGridRequest('_helpdesk_faq'));
echo $grid->run();
}
public function displayassignAction()
{
if (!$this->strategy->canEditOwner(null)) {
throw new Am_Exception_AccessDenied();
}
$ds = new Am_Query($this->getDi()->adminTable);
$grid = new Am_Grid_ReadOnly('_helpdesk_assign', ___('Admins'), $ds, $this->getRequest(), $this->view, $this->getDi());
$grid->addField('login', ___('Name'))->setRenderFunction(array($this, 'renderAssignTitle'));
$grid->setPermissionId(Bootstrap_Helpdesk::ADMIN_PERM_ID);
$grid->isAjax($this->isAjax() && $this->isGridRequest('_helpdesk_assign'));
echo $grid->run();
}
public function displayeditcategoryAction()
{
if (!$this->strategy->canEditCategory(null)) {
throw new Am_Exception_AccessDenied();
}
$ds = new Am_Query($this->getDi()->helpdeskCategoryTable);
$grid = new Am_Grid_ReadOnly('_helpdesk_category', ___('Categories'), $ds, $this->getRequest(), $this->view, $this->getDi());
$grid->addField('title', ___('Title'))->setRenderFunction(array($this, 'renderEditCategoryTitle'));
$grid->setPermissionId(Bootstrap_Helpdesk::ADMIN_PERM_ID);
$grid->isAjax($this->isAjax() && $this->isGridRequest('_helpdesk_category'));
echo $grid->run();
}
public function editwatcherAction()
{
$ticketIdentity = $this->getParam('ticket');
$ticket = $this->getDi()->helpdeskTicketTable->load($ticketIdentity);
if (!$this->strategy->canEditWatcher($ticket)) {
throw new Am_Exception_AccessDenied();
}
$options = array();
foreach (Am_Di::getInstance()->adminTable->findBy() as $admin) {
$options[$admin->pk()] = sprintf('%s (%s %s)', $admin->login, $admin->name_f, $admin->name_l);
}
$form = new Am_Form_Admin;
$form->addMagicSelect('watcher_ids')
->setLabel(___("Watchers\n" .
'notify the following admins ' .
'about new messages in this ticket'))
->loadOptions($options);
$form->addHidden('ticket')
->setValue($ticketIdentity);
$form->addSaveButton();
if (!$form->isSubmitted()) {
$form->setDataSources(array(new HTML_QuickForm2_DataSource_Array(array(
'watcher_ids' => explode(',', $ticket->watcher_ids)
))));
}
if ($form->isSubmitted() && $form->validate()) {
$vars = $form->getValue();
$ticket->watcher_ids = implode(",", $vars['watcher_ids']);
$ticket->save();
if (!$this->_request->isXmlHttpRequest()) {
return $this->redirectTicket($ticket);
}
}
echo $form;
}
public function renderFaqTitle($record, $fieldName, $grid)
{
return sprintf('%s ',
$this->getDi()->rurl('helpdesk/faq/i/'.urlencode($record->title)),
Am_Html::escape($record->title));
}
public function renderAssignTitle($record, $fieldName, $grid)
{
return sprintf('%s ',
$this->getDi()->app->obfuscate($record->pk()),
Am_Html::escape(sprintf('%s (%s %s)', $record->login, $record->name_f, $record->name_l)));
}
public function renderEditCategoryTitle($record, $fieldName, $grid)
{
return sprintf('%s ',
$this->getDi()->app->obfuscate($record->pk()),
Am_Html::escape($record->title));
}
public function createForm()
{
$form = new Am_Form_Admin();
$form->addText('title', array('class' => 'el-wide'))
->setLabel(___('Title'))
->addRule('required');
$form->addTextarea('content', array('class' => 'el-wide', 'rows' => 10))
->setLabel(___('Content'))
->addRule('required');
return $form;
}
protected function redirectTicket($ticket)
{
$url = $this->strategy->ticketUrl($ticket);
$this->_response->redirectLocation($url);
}
private function editMessage($message_id, $value)
{
$message = $this->getDi()->helpdeskMessageTable->load($message_id);
if (!$this->strategy->canEditMessage($message)) {
throw new Am_Exception_AccessDenied(___('Access Denied'));
}
$message->content = $value['content'];
$message->save();
}
private function addMessage($ticket, $value)
{
$message = $this->getDi()->helpdeskMessageRecord;
$message->content = $value['content'];
$message->ticket_id = $ticket->ticket_id;
$message->type = $value['type'];
$message->setAttachments($value['attachments']);
$message = $this->strategy->fillUpMessageIdentity($message);
$message->save();
$this->strategy->onAfterInsertMessage($message, $ticket);
$ticket->status = $this->strategy->getTicketStatusAfterReply($message);
$ticket->updated = $this->getDi()->sqlDateTime;
$ticket->save();
if (isset($value['_close']) && $value['_close'] && $this->strategy->caneditTicket($ticket)) {
$ticket->status = HelpdeskTicket::STATUS_CLOSED;
$ticket->save();
}
}
private function reply($ticket, $message_id, $values)
{
if ($message_id) {
$this->editMessage($message_id, $values);
} else {
$this->addMessage($ticket, $values);
}
}
private function getReplyForm($ticket, $message = null, $type = 'message')
{
$content = '';
$form = $this->strategy->createForm();
if (!is_null($message) && $type == 'message') {
if (!$this->getModule()->getConfig('does_not_quote_in_reply')) {
$content = explode("\n", $message->content);
$content = array_map(function($v) { return '>'.$v; }, $content);
$content = "\n\n" . implode("\n", $content);
}
} elseif (!is_null($message) && $type == 'comment') {
$content = $message->content;
$form->addHidden('message_id')
->setValue($this->getDi()->app->obfuscate($message->message_id));
}
if ($type == 'message' &&
defined('AM_ADMIN') &&
$this->getModule()->getConfig('add_signature')) {
$content = "\n\n" . $this->expandPlaceholders($this->getModule()->getConfig('signature')) . $content;
}
$form->addHidden('type')
->setValue($type);
$row_num = min(15, count(explode("\n", $content))+1);
$form->addTextarea('content', array('rows' => $row_num,
'class' => 'no-label el-wide',
'placeholder' => $type == 'comment' ? ___('Write your comment...') : ___('Write your reply...')))
->setValue($content)
->addRule('required');
$form->setAction($this->strategy->assembleUrl(array(
'page_id' => 'view',
'action' => 'reply',
'ticket' => $ticket,
'type' => $type
), 'inside-pages'));
if ($type != 'comment') {
$this->strategy->addUpload($form);
}
if ($this->strategy->canEditTicket($ticket)) {
$form->addAdvCheckbox('_close', null, array('content' => ___('Close This Ticket After Response')));
}
$btns = $form->addGroup();
$btns->setSeparator(' ');
$btns->addSubmit('submit', array('value' => ___('Send Message')));
$btns->addInputButton('discard', array('value' => ___('Discard')));
return $form;
}
protected function expandPlaceholders($text)
{
$admin = $this->getDi()->authAdmin->getUser();
return str_replace(array(
'%name_f%', '%name_l%'
), array(
$admin->name_f, $admin->name_l
), $text);
}
}
class Am_View_Helper_HelpdeskGetTicketField extends Zend_View_Helper_Abstract
{
protected $customFields = array();
function __construct($customFields)
{
$this->customFields = $customFields;
}
public function helpdeskGetTicketField(HelpdeskTicket $ticket, $field_name)
{
return $this->formatValue($this->getValue($ticket, $field_name), $field_name);
}
protected function getValue(HelpdeskTicket $ticket, $field_name)
{
return $this->customFields[$field_name]->sql ?
$ticket->{$field_name} :
$ticket->data()->get($field_name);
}
protected function formatValue($val, $field_name)
{
if (isset($this->customFields[$field_name])) {
$field = $this->customFields[$field_name];
switch($field->getType()) {
case 'date':
$res = amDate($val);
break;
case 'select':
case 'radio':
case 'checkbox':
case 'multi_select':
$val = (array)$val;
foreach ($val as $k=>$v)
$val[$k] = @$field->options[$v];
$res = implode(", ", $val);
break;
default:
$res = $val;
}
} else {
$res = $val;
}
return $res;
}
}PK \{\r1 r1 % helpdesk/library/Am/Helpdesk/Grid.phpnu [ status = HelpdeskTicket::STATUS_CLOSED;
$record->save();
}
}
class Am_Grid_Editable_Helpdesk extends Am_Grid_Editable
{
protected $foundRowsBeforeFilter = 0;
protected $eventId = 'gridHelpdesk';
function init()
{
$this->foundRowsBeforeFilter = $this->dataSource->getFoundRows();
$this->addCallback(Am_Grid_ReadOnly::CB_RENDER_TABLE, array($this, 'skipTable'));
}
function renderFilter()
{
if ($this->foundRowsBeforeFilter) {
return parent::renderFilter();
}
}
function skipTable(& $out)
{
if (!$this->foundRowsBeforeFilter) {
$out = '';
}
}
public function getPermissionId()
{
return Bootstrap_Helpdesk::ADMIN_PERM_ID;
}
}
class Am_Grid_Filter_Helpdesk extends Am_Grid_Filter_Abstract
{
protected $language = null;
protected $varList = array('filter_q', 'has_new');
protected function applyFilter()
{
$query = $this->grid->getDataSource()->getDataSourceQuery();
if ($filter = $this->getParam('filter_q')) {
$condition = new Am_Query_Condition_Field('subject', 'LIKE', '%' . $filter . '%');
$condition->_or(new Am_Query_Condition_Field('ticket_mask', 'LIKE', '%' . $filter . '%'));
$query->add($condition);
}
if ($this->getParam('has_new')) {
$query->addWhere('t.has_new=?', 1);
}
}
function renderInputs()
{
$filter = $this->renderInputText(array(
'placeholder' => ___('Subject or Ticket#'),
'name' => 'filter_q'));
return $filter;
}
function getTitle()
{
return '';
}
}
class Am_Grid_Filter_Helpdesk_Adv extends Am_Grid_Filter_Helpdesk
{
protected $language = null;
protected $varList = array('filter_q', 'filter_c', 'has_new');
protected function applyFilter()
{
parent::applyFilter();
$query = $this->grid->getDataSource()->getDataSourceQuery();
if ($filter = $this->getParam('filter_c')) {
$query->addWhere('t.category_id=?', $filter);
}
}
function renderInputs()
{
$filter = parent::renderInputs();
$categoryOptions = Am_Di::getInstance()->helpdeskCategoryTable->getOptions();
if ($categoryOptions) {
$categoryOptions = array('' => ___('All Categories')) + $categoryOptions;
$filter .= ' ';
$filter .= $this->renderInputSelect('filter_c', $categoryOptions);
}
return $filter;
}
function getTitle()
{
return '';
}
}
class Am_Grid_Filter_Helpdesk_Adv_WithStatus extends Am_Grid_Filter_Helpdesk_Adv
{
protected $varList = array('filter_q', 'filter_s', 'filter_c', 'has_new');
protected function applyFilter()
{
parent::applyFilter();
$query = $this->grid->getDataSource()->getDataSourceQuery();
if ($filter = $this->getParam('filter_s')) {
$query->addWhere('t.status IN (?a)', $filter);
}
}
function renderInputs()
{
$categoryOptions = Am_Di::getInstance()->helpdeskCategoryTable->getOptions();
$width = $categoryOptions ? '45' : '90';
$filter = $this->renderInputText(array(
'placeholder' => ___('Subject or Ticket#'),
'name' => 'filter_q',
'style' => "width:$width%"));
if ($categoryOptions) {
$categoryOptions = array('' => ___('All Categories')) + $categoryOptions;
$filter .= ' ';
$filter .= $this->renderInputSelect('filter_c', $categoryOptions, array(
'style' => "width:$width%"
));
}
$statusOptions = HelpdeskTicket::getStatusOptions();
unset($statusOptions[HelpdeskTicket::STATUS_CLOSED]);
$filter .= ' ';
$filter .= $this->renderInputCheckboxes('filter_s', $statusOptions);
return $filter;
}
}
class Am_Grid_Action_Ticket extends Am_Grid_Action_Abstract
{
protected $type = self::NORECORD; // this action does not operate on existing records
protected $strategy = null;
public function __construct($id = null, $title = null)
{
$this->title = ___('Submit New Ticket');
parent::__construct($id, $title);
}
public function run()
{
$form = $this->grid->getForm();
if ($form->isSubmitted() && $form->validate()) {
$values = $form->getValue();
if (defined('AM_ADMIN')
&& AM_ADMIN
&& isset($values['from'])
&& $values['from'] == 'user') {
$user = Am_Di::getInstance()->userTable->findFirstByLogin($values['loginOrEmail']);
if (!$user)
$user = Am_Di::getInstance()->userTable->findFirstByEmail($values['loginOrEmail']);
if (!$user)
throw new Am_Exception_InputError("User not found with username or email equal to {$values['loginOrEmail']}");
$this->switchStrategy(new Am_Helpdesk_Strategy_User(Am_Di::getInstance(), $user->pk()));
}
$ticket = Am_Di::getInstance()->helpdeskTicketRecord;
if (isset($values['category_id']) && isset($values['category'][$values['category_id']])) {
$ticket->setForInsert($values['category'][$values['category_id']]);
} elseif (isset($values['additional'])) {
$ticket->setForInsert($values['additional']);
}
$ticket->subject = $values['subject'];
$ticket->created = Am_Di::getInstance()->sqlDateTime;
$ticket->updated = Am_Di::getInstance()->sqlDateTime;
$ticket->category_id = isset($values['category_id']) ? $values['category_id'] : null;
if (($category = $ticket->getCategory()) && ($category->owner_id || $category->watcher_ids)) {
$ticket->owner_id = $category->owner_id;
$ticket->watcher_ids = $category->watcher_ids;
}
$ticket = $this->getStrategy()->fillUpTicketIdentity($ticket, $this->grid->getCompleteRequest());
// mask will be generated on insertion
$ticket->insert();
$this->getStrategy()->onAfterInsertTicket($ticket);
$content = $values['content'];
if (defined('AM_ADMIN')
&& AM_ADMIN) {
$user = $ticket->getUser();
$tpl = new Am_SimpleTemplate;
$tpl->assign('user', $user);
$content = $tpl->render($content);
}
$message = Am_Di::getInstance()->helpdeskMessageRecord;
$message->content = $content;
$message->ticket_id = $ticket->pk();
$message->dattm = Am_Di::getInstance()->sqlDateTime;
$message = $this->getStrategy()->fillUpMessageIdentity($message);
$message->setAttachments(@$values['attachments']);
$message->insert();
$this->getStrategy()->onAfterInsertMessage($message, $ticket);
$this->restoreStrategy();
echo $this->renderTicketSubmited($ticket);
} else {
echo $this->renderTitle();
echo $form;
}
}
/** @return Am_Helpdesk_Strategy_Abstract */
protected function getStrategy()
{
return is_null($this->strategy) ?
Am_Di::getInstance()->helpdeskStrategy :
$this->strategy;
}
public function switchStrategy(Am_Helpdesk_Strategy_Abstract $strategy)
{
$this->strategy = $strategy;
}
public function restoreStrategy()
{
if (!is_null($this->strategy)) {
$this->strategy = null;
}
}
protected function renderTicketSubmited($ticket)
{
$out = sprintf('%s ', ___('Ticket has been submited'));
$out .= sprintf('%s #%s
',
___('Reference number is:'),
$this->getStrategy()->ticketUrl($ticket),
$ticket->ticket_mask
);
return $out;
}
}
abstract class Am_Helpdesk_Grid extends Am_Grid_Editable_Helpdesk
{
public function __construct(Am_Mvc_Request $request, Am_View $view)
{
$id = explode('_', get_class($this));
$id = strtolower(array_pop($id));
parent::__construct('_' . $id, $this->getGridTitle(), $this->createDs(), $request, $view);
if ($f = $this->createFilter()) {
$this->setFilter($f);
}
$this->setRecordTitle(array($this, 'getTicketRecordTitle'));
}
protected function createFilter()
{
return new Am_Grid_Filter_Helpdesk_Adv_WithStatus;
}
abstract function getStatusIconId($id, $record);
public function getTicketRecordTitle(HelpdeskTicket $ticket = null)
{
return $ticket ? sprintf('%s (#%s: %s)',
___('Ticket'), $ticket->ticket_mask, $ticket->subject) :
___('Ticket');
}
public function cbGetTrAttribs(& $ret, $record)
{
if ($this->isNotImportant($record)) {
$ret['class'] = isset($ret['class']) ? $ret['class'] . ' disabled' : 'disabled';
}
}
protected function isNotImportant($record)
{
return false;
}
public function initActions()
{
//nop
}
public function createForm()
{
return $this->getDi()->helpdeskStrategy->createNewTicketForm();
}
public function renderSubject($r)
{
$url = $this->getDi()->helpdeskStrategy->ticketUrl($r);
$category = $r->category_id && $r->c_title ?
sprintf(' %s', Am_Html::escape($r->c_title)) :
'';
return sprintf('%s %d %s %s ',
$url,
Am_Html::escape($r->subject),
$r->msg_cnt,
Am_Html::escape(mb_substr(preg_replace('/(\s{2,})/m', ' ', strip_tags(trim($r->msg_last))), 0, 70)) . '…',
$category
);
}
public function renderStatus($record)
{
$statusOptions = HelpdeskTicket::getStatusOptions();
list($status) = explode('_', $record->status);
$status = $this->getStatusIconId($status, $record);
return sprintf('%s ',
$this->getDi()->view->icon($status, $statusOptions[$record->status])
);
}
public function renderTime($record, $fieldName)
{
return sprintf('%s ', amDatetime($record->$fieldName), date('c', amstrtotime($record->$fieldName)), $this->getView()->getElapsedTime($record->$fieldName));
}
public function renderUser($record, $fieldName)
{
$name = trim("{$record->m_name_f} {$record->m_name_l}");
return sprintf('%s%s ',
$this->getView()->userUrl($record->user_id),
$record->m_login,
$name ? sprintf(' (%s)', Am_Html::escape($name)) : ''
);
}
protected function createDS()
{
$query = new Am_Query(Am_Di::getInstance()->helpdeskTicketTable);
$query->addField('COUNT(msg.message_id)', 'msg_cnt')
->addField('(SELECT content FROM ?_helpdesk_message '
. 'WHERE ticket_id = t.ticket_id '
. 'ORDER BY dattm DESC LIMIT 1)', 'msg_last')
->addField('m.login AS m_login')
->addField('m.name_f AS m_name_f')
->addField('m.name_l AS m_name_l')
->addField('m.email AS m_email')
->leftJoin('?_helpdesk_message', 'msg', 'msg.ticket_id=t.ticket_id')
->addWhere('msg.type=?', 'message')
->leftJoin('?_user', 'm', 't.user_id=m.user_id')
->leftJoin('?_helpdesk_category', 'c', 't.category_id=c.category_id')
->addField('c.title', 'c_title')
->addOrder('updated', true);
if (Am_Di::getInstance()->plugins_misc->isEnabled('avatar')) {
$query->addField('m.avatar', 'm_avatar');
}
return $query;
}
public function getGridTitle()
{
return ___('Tickets');
}
}PK \]N N 5 helpdesk/library/Am/Helpdesk/Grid/Admin/Dashboard.phpnu [ addWhere('t.status<>?', HelpdeskTicket::STATUS_CLOSED);
return $q;
}
public function initActions()
{
parent::initActions();
$this->actionAdd(new Am_Grid_Action_Ticket());
$this->actionAdd(new Am_Grid_Action_Delete());
if ($cnt = $this->getDi()->helpdeskTicketTable->countByStatus(HelpdeskTicket::STATUS_CLOSED)) {
$this->actionAdd(new Am_Grid_Action_Url('archive', ___('Closed Tickets') . " ($cnt)",
$this->getDi()->url('helpdesk/admin/archive')))
->setType(Am_Grid_Action_Abstract::NORECORD)
->setTarget('_top')
->setCssClass('link');
}
}
}PK \I;$ 3 helpdesk/library/Am/Helpdesk/Grid/Admin/Archive.phpnu [ addWhere('t.status=?', HelpdeskTicket::STATUS_CLOSED);
return $q;
}
public function getGridTitle()
{
return ___('Archive');
}
public function initActions()
{
parent::initActions();
$this->actionAdd(new Am_Grid_Action_Delete());
$this->actionDelete('ticket');
if ($cnt = $this->getDi()->helpdeskTicketTable->countBy(array(
'status' => '<>' . HelpdeskTicket::STATUS_CLOSED))) {
$this->actionAdd(new Am_Grid_Action_Url('dashboard', ___('Dashboard') . " ($cnt)",
$this->getDi()->url('helpdesk/admin')))
->setType(Am_Grid_Action_Abstract::NORECORD)
->setTarget('_top')
->setCssClass('link');
}
}
}
PK \VIMj j + helpdesk/library/Am/Helpdesk/Grid/Admin.phpnu [ getDataSource();
$ds->leftJoin('?_admin', 'a', 't.owner_id=a.admin_id')
->addField("CONCAT(a.login, ' (',a.name_f, ' ', a.name_l, ')')", 'owner');
if ($this->getDi()->plugins_misc->isEnabled('avatar') &&
$this->getDi()->modules->get('helpdesk')->getConfig('show_avatar')) {
$this->addField(new Am_Grid_Field('avatar', '', false, '', array($this, 'renderAvatar'), '1%'));
} elseif ($this->getDi()->modules->get('helpdesk')->getConfig('show_gravatar')) {
$this->addField(new Am_Grid_Field('gravatar', '', false, '', array($this, 'renderGravatar'), '1%'));
}
$this->addField(new Am_Grid_Field('m_login', ___('User'), true, '', array($this, 'renderUser')));
$this->addField(new Am_Grid_Field('subject', ___('Subject'), true, '', array($this, 'renderSubject')));
$this->addField(new Am_Grid_Field_Date('created', ___('Created')))->setFormatDate();
$this->addField(new Am_Grid_Field('updated', ___('Updated'), true, '', array($this, 'renderTime')));
if ($this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_helpdesk_ticket WHERE owner_id IS NOT NULL")) {
$this->addField(new Am_Grid_Field('owner_id', ___('Owner'), true, '', array($this, 'renderOwner')));
}
$this->addField(new Am_Grid_Field('ticket_mask', ___('Ticket#'), true));
$this->addField(new Am_Grid_Field('status', ___('Status'), true, '', array($this, 'renderStatus'), '1%'));
$this->addCallback(Am_Grid_ReadOnly::CB_TR_ATTRIBS, array($this, 'cbGetTrAttribs'));
}
public function initActions()
{
parent::initActions();
$this->actionAdd(new Am_Grid_Action_Delete);
$this->actionAdd(new Am_Grid_Action_Group_CloseTicket);
$this->actionAdd(new Am_Grid_Action_Group_Delete);
}
public function getStatusIconId($id, $record)
{
return ($id == 'awaiting' && $record->status == HelpdeskTicket::STATUS_AWAITING_ADMIN_RESPONSE ?
$id . '-me' : $id);
}
public function renderOwner($record)
{
return $record->owner_id ?
sprintf('%s ', Am_Html::escape(str_replace(' ( )', '', $record->owner))) :
' ';
}
public function renderGravatar($record)
{
return sprintf(' ',
'//www.gravatar.com/avatar/' . md5(strtolower(trim($record->m_email))) . '?s=40&d=mm');
}
public function renderAvatar($record)
{
return sprintf(' ',
$this->getDi()->url('misc/avatar/' . $record->m_avatar));
}
protected function isNotImportant($record)
{
return $record->status == HelpdeskTicket::STATUS_AWAITING_USER_RESPONSE;
}
}PK \">~ ( helpdesk/library/Am/View/Helper/Skip.phpnu [ $v) {
if (preg_match('/^\s*>\s*>/', trim($v))) {
$s_arr[$k] = 1;
} else {
$s_arr[$k] = 0;
}
}
//add one none skiped line at the end
//in order to resolve problem if last line should be skiped too
$arr[] = '';
$arr = array_map(array('Am_Html', 'escape'), $arr);
$s_arr[] = 0;
//remove empty lines beetween skiped lines
$prev = 0;
$empty_lines = array();
foreach ($s_arr as $k => $v) {
if (trim($arr[$k]) == '') {
$empty_lines[] = $k;
} elseif ($v && $prev) {
foreach ($empty_lines as $key) {
$s_arr[$key] = 1;
}
$empty_lines = array();
$prev = 1;
} elseif ($v) {
$empty_lines = array();
$prev = 1;
} else {
$prev = 0;
}
}
//skip
$skiped = 0;
$skiped_lines = array();
$label_lines_skipped = ___('lines skipped');
foreach ($s_arr as $k => $v) {
if ($v) {
$skiped_lines[] = $arr[$k];
if (!$skiped) {
$first_skiped_line = $k;
} else {
unset($arr[$k]);
}
$skiped++;
} elseif ($skiped) {
$arr[$first_skiped_line] = '...' . $skiped . ' ' . $label_lines_skipped . '...
' . implode("\n", $skiped_lines) . ' ';
$skiped = 0;
$skiped_lines = array();
}
}
$string = implode("\n", $arr);
return $string;
}
}PK \گu ; ; . helpdesk/library/Am/View/Helper/Hyperlinks.phpnu [ ".?,)]{0,1}(\s|$))|(&(quot|gt);))#i';
return preg_replace($pattern, '$1 $3', $string);
}
}PK \m helpdesk/library/SetupForms.phpnu [ setTitle(___('Helpdesk'));
$this->data['help-id'] = 'Setup/Helpdesk';
}
function initElements()
{
$fieldSetNotifications = $this->addFieldset()
->setLabel(___('Notifications'));
$fieldSetNotifications->addElement('email_checkbox', 'helpdesk.notify_new_message', null, array('help-id' => '#Enabling.2FDisabling_Customer_Notifications'))
->setLabel(___("Send Notification about New Messages to Customer\n" .
"aMember will email a notification to user " .
"each time admin responds to a user ticket"));
$this->setDefault('helpdesk.notify_new_message', 1);
$fieldSetNotifications->addElement('email_checkbox', 'helpdesk.notify_new_message_admin')
->setLabel(___("Send Notification about New Messages to Admin\n" .
"aMember will email a notification to admin " .
"each time user responds to a ticket"));
$this->setDefault('helpdesk.notify_new_message_admin', 1);
$fieldSetNotifications->addElement('email_checkbox', 'helpdesk.new_ticket')
->setLabel(___("New Ticket Autoresponder to Customer\n" .
"aMember will email an autoresponder to user " .
"each time user create new ticket"));
$fieldSetNotifications->addElement('email_checkbox', 'helpdesk.notify_assign')
->setLabel(___("Send Notification When Ticket is Assigned to Admin\n" .
"aMember will email a notification to admin " .
"each time ticket is assigned to him"));
$fieldSetConversation = $this->addFieldset()
->setLabel(___('Conversation'));
$fieldSetConversation->addAdvCheckbox('helpdesk.can_edit')
->setLabel(___("Admin Can Edit His Messages\n" .
"within 5 minutes after post"));
$fieldSetConversation->addAdvCheckbox('helpdesk.add_signature')
->setLabel(___('Add Signature to Response'));
$fieldSetConversation->addTextarea('helpdesk.signature', array('rows'=>3, 'class'=>'el-wide'))
->setLabel(___("Signature Text\n" .
"You can use the following placeholders %name_f%, %name_l% " .
"it will be expanded to first and last name of admin in operation"));
$this->addScript('script')
->setScript(<<addAdvCheckbox('helpdesk.disclosure_admin')
->setLabel(___("Disclosure Admin real name in user interface\n" .
"otherwise only word Administrator is shown"));
$fieldSetConversation->addAdvCheckbox('helpdesk.does_not_quote_in_reply')
->setLabel(___('Does Not Quote Message in Reply'));
$fieldSetConversation->addAdvCheckbox('helpdesk.does_not_allow_attachments')
->setLabel(___('Does Not Allow to Upload Attachments for Users'));
$gr = $fieldSetConversation->addGroup()
->setLabel(___("Autoclose Tickets Due to Inactivity"));
$gr->addAdvCheckbox('helpdesk.autoclose')
->setId('helpdesk_autoclose');
$gr->addStatic()->setContent(sprintf(' %s ', ___("after")));
$gr->addText('helpdesk.autoclose_period', array('class'=>'helpdesk_autoclose_hours', 'size' => 3, 'placeholder'=>70));
$gr->addStatic()->setContent(sprintf(' %s ', ___("hours")));
$fieldSetConversation->addElement('email_checkbox', 'helpdesk.notify_autoclose')
->setLabel(___("Send Autoclose Notification to User\n" .
"aMember will email an autoresponder to user " .
"when ticket is closed due to inactivity"));
$this->addScript()->setScript(<<addFieldset()
->setLabel(___('Features'));
$fieldSetFeatures->addAdvCheckbox('helpdesk.live')
->setLabel(___("Enable Live Conversation (experimental)\n" .
"update conversation instantly without page reload (can consume more server resources)"));
$fieldSetFeatures->addAdvCheckbox('helpdesk.show_gravatar')
->setId('gravatar')
->setLabel(___("Show Gravatars in Ticket Conversation\n" .
'more details about gravatar can be found %shere%s',
'',
' '));
if (Am_Di::getInstance()->plugins_misc->isEnabled('avatar')) {
$fieldSetFeatures->addAdvCheckbox('helpdesk.show_avatar')
->setId('avatar')
->setLabel(___("Show Avatars in Ticket Conversation\n" .
'this option has priority over gravatar if enabled'));
$this->addScript()->setScript(<<addAdvCheckbox('helpdesk.does_not_require_login')
->setLabel(___("Does Not Require Login to Access FAQ Section\n" .
'make it public'));
$fieldSetFeatures->addAdvCheckbox('helpdesk.does_not_show_faq_tab')
->setLabel(___('Does Not Show FAQ Tab in Member Area'));
$fieldSetFeatures->addAdvCheckbox('helpdesk.show_faq_search')
->setLabel(___('Show Search Function in FAQ'));
$this->addHtmlEditor('helpdesk.intro', null, array('showInPopup' => true))
->setLabel(___("Intro Text on Helpdesk Page"));
$this->setDefault('helpdesk.intro', 'We answer customer tickets Mon-Fri, 10am - 5pm EST. You can also call us by phone if you have an urgent question.');
}
}
PK \[JF F # helpdesk/library/HelpdeskTicket.phpnu [ ___('New'),
'awaiting_admin_response' => ___('Awaiting Admin Response'),
'awaiting_user_response' => ___('Awaiting User Response'),
'closed' => ___('Closed')
);
}
public function getMessages()
{
return $this->getDi()->helpdeskMessageTable->findBy(
array('ticket_id' => $this->pk()),
null, null, "dattm DESC");
}
/**
* @return User
*/
public function getUser()
{
return $this->getDi()->userTable->load($this->user_id);
}
/**
* @return Admin
*/
public function getOwner()
{
return $this->owner_id ? $this->getDi()->adminTable->load($this->owner_id, false) : null;
}
public function getWatchers()
{
$res = array();
foreach (explode(',', $this->watcher_ids) as $id) {
if ($id && $admin = $this->getDi()->adminTable->load($id, false)) {
$res[] = $admin;
}
}
return $res;
}
/**
* @return HelpdeskCategory
*/
public function getCategory()
{
return $this->category_id ? $this->getDi()->helpdeskCategoryTable->load($this->category_id, false) : null;
}
public function isLocked(Admin $admin)
{
return $this->lock_until &&
($this->lock_until > sqlTime('now')) &&
($this->lock_admin_id != $admin->pk());
}
public function lock(Admin $admin)
{
$this->updateQuick(array(
'lock_until' => sqlTime('+2 minutes'),
'lock_admin_id' => $admin->pk(),
'lock_admin' => sprintf('%s (%s %s)', $admin->login, $admin->name_f, $admin->name_l)
));
}
protected function _generateMask()
{
if (!empty($this->ticket_mask))
return;
$this->ticket_mask =
$this->getDi()->security->randomString(3, 'ABCDEFGJIKLMNOPQRSTUVWXYZ')
. '-' . rand(100000, 999999);
}
/**
* before record insertion generate new ticket mask. if the generated mask is not unique,
* try 20 times to generate new mask, then throw exception
* @return type
*/
public function insert($reload = true)
{
$event = new Am_Event(Bootstrap_Helpdesk::EVENT_TICKET_BEFORE_INSERT, array(
'ticket' => $this
));
$this->getDi()->hook->call($event);
$maxAttempts = 20;
for ($i = 0; $i <= $maxAttempts; $i++) {
try {
$this->_generateMask();
parent::insert($reload);
$event = new Am_Event(Bootstrap_Helpdesk::EVENT_TICKET_AFTER_INSERT, array(
'ticket' => $this
));
$this->getDi()->hook->call($event);
return $this;
} catch (Am_Exception_Db_NotUnique $e) {
if ($i >= $maxAttempts)
throw new Am_Exception_InternalError("Could not generate new ticket mask after [$i] attempts");
$this->ticket_mask = null;
}
}
}
public function delete()
{
foreach ($this->getMessages() as $msg) {
$msg->delete();
}
parent::delete();
}
}
class HelpdeskTicketTable extends Am_Table_WithData
{
protected $_key = 'ticket_id';
protected $_table = '?_helpdesk_ticket';
protected $_recordClass = 'HelpdeskTicket';
public function insert(array $values, $returnInserted = false)
{
if (empty($values['created']))
$values['created'] = $this->getDi()->sqlDateTime;
return parent::insert($values, $returnInserted);
}
public function load($keyOrTicketId, $throwExceptions = true)
{
if (preg_match('/^\d+$/', trim($keyOrTicketId), $matches))
return parent::load($matches[0], $throwExceptions);
else {
$keyOrTicketId = filterId($keyOrTicketId);
$found = $this->findFirstByTicketMask($keyOrTicketId);
if (!$found && $throwExceptions)
throw new Am_Exception_InternalError("Ticket with mask [$keyOrTicketId] not found");
return $found;
}
}
public function clearOld($date)
{
foreach ($this->findByUpdated('<' . $date) AS $ticket) {
$ticket->delete();
}
}
}PK \r $ helpdesk/library/HelpdeskSnippet.phpnu [
helpdesk.notify_new_message
1
en
text
%site_title%: New Message for Your Ticket [#%ticket.ticket_mask%]
You have received a new message in helpdesk
for your ticket [%ticket.subject%]
Follow a link below to view this message:
%url%
helpdesk.notify_new_message_admin
2
en
text
%site_title%: New Message for Ticket [#%ticket.ticket_mask%]
You have received a new message in helpdesk
for ticket [%ticket.subject%]
Follow a link below to view this message:
%url%
helpdesk.new_ticket
1
en
text
%site_title%: New Ticket [#%ticket.ticket_mask%]
You created ticket [%ticket.subject%]
in our helpdesk system.
Thank you for your enquiry.
We will respond within 24 hours.
Follow a link below to view your ticket:
%url%
helpdesk.notify_assign
2
en
text
%site_title%: Ticket [#%ticket.ticket_mask%] is assigned to you
Ticket [%ticket.subject%]
is assigned to you.
Follow a link below to view this ticket:
%url%
helpdesk.notify_autoclose
1
en
text
%site_title%: Ticket [#%ticket.ticket_mask%] has been closed automatically
Your ticket [%ticket.subject%] has been closed automatically due to inactivity.
If the issue hasn't been resolved to your satisfaction yet please let us know.
Follow a link below to view this ticket:
%url%
PK \"/k^L ^L helpdesk/Bootstrap.phpnu [ getDi()->uploadTable->defineUsage(self::ATTACHMENT_UPLOAD_PREFIX, 'helpdesk_message', 'attachments', UploadTable::STORE_IMPLODE, "Ticket [%ticket_id%]", '/helpdesk/admin/p/index/index');
$this->getDi()->uploadTable->defineUsage(self::ADMIN_ATTACHMENT_UPLOAD_PREFIX, 'helpdesk_message', 'attachments', UploadTable::STORE_IMPLODE, "Ticket [%ticket_id%]", '/helpdesk/admin/p/index/index');
}
function renderNotification()
{
if ($user_id = $this->getDi()->auth->getUserId()) {
$cnt = $this->getDi()->db->selectCell("SELECT COUNT(ticket_id) FROM ?_helpdesk_ticket WHERE has_new=? AND user_id=?", 1, $user_id);
if ($cnt) {
return '';
}
}
}
function onSetupEmailTemplateTypes(Am_Event $event)
{
$ticket = array(
'ticket.ticket_mask' => 'Ticket Mask',
'ticket.subject' => 'Ticket Subject',
);
$event->addReturn(array(
'id' => 'helpdesk.notify_new_message',
'title' => 'Notify New Message',
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'vars' => $ticket + array('url' => 'Url of Page with Message', 'user'),
), 'helpdesk.notify_new_message');
$event->addReturn(array(
'id' => 'helpdesk.notify_new_message',
'title' => 'Notify New Message',
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'isAdmin' => true,
'vars' => $ticket + array('url' => 'Url of Page with Message', 'user'),
), 'helpdesk.notify_new_message_admin');
$event->addReturn(array(
'id' => 'helpdesk.new_ticket',
'title' => 'Autoresponder New Ticket',
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'vars' => $ticket + array('url' => 'Url of Page with Ticket', 'user'),
), 'helpdesk.new_ticket');
$event->addReturn(array(
'id' => 'helpdesk.notify_assign',
'title' => 'Notify Ticket is Assigned to Admin',
'mailPeriodic' => Am_Mail::ADMIN_REQUESTED,
'vars' => $ticket + array('url' => 'Url of Page with Ticket', 'admin'),
'isAdmin' => true,
), 'helpdesk.notify_assign');
$event->addReturn(array(
'id' => 'helpdesk.notify_autoclose',
'title' => 'Notify User about Ticket Autoclose',
'mailPeriodic' => Am_Mail::USER_REQUESTED,
'vars' => array('user') + $ticket + array('url' => 'Url of Page with Ticket'),
), 'helpdesk.notify_autoclose');
}
function onGetUploadPrefixList(Am_Event $event)
{
$event->addReturn(array(
Am_Upload_Acl::IDENTITY_TYPE_ADMIN => array(
self::ADMIN_PERM_ID => Am_Upload_Acl::ACCESS_ALL
)
), self::ADMIN_ATTACHMENT_UPLOAD_PREFIX);
if (!$this->getConfig('does_not_allow_attachments')) {
$event->addReturn(array(
Am_Upload_Acl::IDENTITY_TYPE_ADMIN => array(
self::ADMIN_PERM_ID => Am_Upload_Acl::ACCESS_ALL
),
Am_Upload_Acl::IDENTITY_TYPE_USER => Am_Upload_Acl::ACCESS_WRITE | Am_Upload_Acl::ACCESS_READ_OWN
), self::ATTACHMENT_UPLOAD_PREFIX);
}
}
function onLoadAdminDashboardWidgets(Am_Event $event)
{
$event->addReturn(new Am_Widget('helpdesk-messages', ___('Last Messages in Helpdesk'), array($this, 'renderWidget'), Am_Widget::TARGET_ANY, array($this, 'createWidgetConfigForm'), self::ADMIN_PERM_ID));
}
function onAdminAfterDelete(Am_Event $e)
{
$this->getDi()->db->query("UPDATE ?_helpdesk_ticket SET owner_id = NULL WHERE owner_id=?", $e->getAdmin()->pk());
$this->getDi()->db->query("UPDATE ?_helpdesk_ticket SET lock_admin_id = NULL,
lock_admin = NULL,
lock_until = NULL WHERE lock_admin_id=?", $e->getAdmin()->pk());
}
function createWidgetConfigForm()
{
$form = new Am_Form_Admin();
$form->addInteger('num')
->setLabel(___('Number of Messages to display'))
->setValue(5);
return $form;
}
function renderWidget(Am_View $view, $config = null)
{
$view->num = is_null($config) ? 5 : $config['num'];
return $view->render('admin/helpdesk/widget/messages.phtml');
}
function onClearItems(Am_Event $event)
{
$event->addReturn(array(
'method' => array($this->getDi()->helpdeskTicketTable, 'clearOld'),
'title' => 'Helpdesk Tickets',
'desc' => 'records with last update date early than Date to Purge'
), 'helpdesk_tickets');
}
function onAdminNotice(Am_Event $e)
{
/* @var $admin Admin */
$admin = $this->getDi()->authAdmin->getUser();
if (!$admin->hasPermission(self::ADMIN_PERM_ID)) return;
$cnt = $this->getDi()->helpdeskTicketTable
->countByStatus(array(
HelpdeskTicket::STATUS_AWAITING_ADMIN_RESPONSE,
HelpdeskTicket::STATUS_NEW));
if ($cnt) {
$e->addReturn(___('You have %s%d ticket(s)%s that require your attention',
sprintf('',
$this->getDi()->url('helpdesk/admin?_dashboard_filter_s[]=new&_dashboard_filter_s[]=awaiting_admin_response')), $cnt, ' '));
}
}
function onUserMerge(Am_Event $event)
{
$target = $event->getTarget();
$source = $event->getSource();
$this->getDi()->db->query('UPDATE ?_helpdesk_ticket SET user_id=? WHERE user_id=?',
$target->pk(), $source->pk());
}
function onAdminMenu(Am_Event $event)
{
$cntMy = $this->getDi()->helpdeskTicketTable->countBy(array(
'owner_id' => $this->getDi()->authAdmin->getUserId(),
'status' => array(
HelpdeskTicket::STATUS_AWAITING_ADMIN_RESPONSE,
HelpdeskTicket::STATUS_NEW)));
$cntDashboard = $this->getDi()->helpdeskTicketTable
->countByStatus(array(
HelpdeskTicket::STATUS_AWAITING_ADMIN_RESPONSE,
HelpdeskTicket::STATUS_NEW));
$event->getMenu()->addPage(array(
'label' => ___('Helpdesk'),
'uri' => '#',
'id' => 'helpdesk',
'resource' => self::ADMIN_PERM_ID,
'pages' => array(
array(
'label' => ___('Dashboard') . ($cntDashboard ? " (($cntDashboard))" : ''),
'controller' => 'admin',
'action' => 'index',
'module' => 'helpdesk',
'id' => 'helpdesk-ticket',
'resource' => self::ADMIN_PERM_ID
),
array(
'label' => ___('My Tickets') . ($cntMy ? " (($cntMy))" : ''),
'controller' => 'admin-my',
'action' => 'index',
'module' => 'helpdesk',
'id' => 'helpdesk-ticket-my',
'resource' => self::ADMIN_PERM_ID
),
array(
'label' => ___('Categories'),
'controller' => 'admin-category',
'action' => 'index',
'module' => 'helpdesk',
'id' => 'helpdesk-category',
'resource' => self::ADMIN_PERM_CATEGORY
),
array(
'label' => ___('Fields'),
'controller' => 'admin-fields',
'action' => 'index',
'module' => 'helpdesk',
'id' => 'helpdesk-fields',
'resource' => self::ADMIN_PERM_CATEGORY
),
array(
'label' => ___('FAQ'),
'controller' => 'admin-faq',
'action' => 'index',
'module' => 'helpdesk',
'id' => 'helpdesk-faq',
'resource' => self::ADMIN_PERM_FAQ
))
));
}
function onUserMenu(Am_Event $event)
{
$page = $helpdeskPage = array(
'id' => 'helpdesk',
'label' => ___('Helpdesk'),
'controller' => 'index',
'action' => 'index',
'module' => 'helpdesk',
'order' => 600,
);
if (!$this->getConfig('does_not_show_faq_tab') && $this->getDi()->helpdeskFaqTable->countBy()) {
$page = array(
'id' => 'helpdesk-root',
'label' => ___('Support'),
'uri' => 'javascript:;',
'order' => 600,
'pages' => array(
$helpdeskPage,
array(
'id' => 'helpdesk-faq',
'label' => ___('FAQ'),
'controller' => 'faq',
'action' => 'index',
'module' => 'helpdesk',
'order' => 601,
)
)
);
}
$event->getMenu()->addPage($page);
}
function onUserTabs(Am_Event_UserTabs $event)
{
extract($this->getDi()->db->selectRow("SELECT COUNT(*) AS cnt_all,
COUNT(IF(status IN ('new', 'awaiting_admin_response'), ticket_id, NULL)) AS cnt_open
FROM ?_helpdesk_ticket WHERE user_id=?", $event->getUserId()));
$event->getTabs()->addPage(array(
'id' => 'helpdesk',
'module' => 'helpdesk',
'controller' => 'admin-user',
'action' => 'index',
'params' => array(
'user_id' => $event->getUserId()
),
'label' => ___('Tickets') . sprintf(' (%s)', $cnt_all ? $cnt_open . '/' . $cnt_all: 0),
'order' => 1000,
'resource' => self::ADMIN_PERM_ID,
));
}
function onGetPermissionsList(Am_Event $event)
{
$event->addReturn(___('Helpdesk: Can operate with helpdesk tickets'), self::ADMIN_PERM_ID);
$event->addReturn(___('Helpdesk: FAQ'), self::ADMIN_PERM_FAQ);
$event->addReturn(___('Helpdesk: Categories'), self::ADMIN_PERM_CATEGORY);
}
function onUserAfterDelete(Am_Event_UserAfterDelete $event)
{
$this->getDi()->db->query("DELETE FROM ?_helpdesk_message WHERE
ticket_id IN (SELECT ticket_id FROM ?_helpdesk_ticket
WHERE user_id=?)", $event->getUser()->user_id);
$this->getDi()->db->query("DELETE FROM ?_helpdesk_ticket
WHERE user_id=?", $event->getUser()->user_id);
}
function onHourly()
{
if ($this->getConfig('autoclose')) {
$period = $this->getConfig('autoclose_period', 72);
$thresholdDate = sqlTime("-$period hours");
foreach($this->getDi()->db->selectPage($total, "
SELECT *
FROM ?_helpdesk_ticket
WHERE status=? AND updated < ?
", HelpdeskTicket::STATUS_AWAITING_USER_RESPONSE, $thresholdDate) as $row) {
$ticket = $this->getDi()->helpdeskTicketRecord->fromRow($row);
$ticket->status = HelpdeskTicket::STATUS_CLOSED;
$ticket->updated = $this->getDi()->sqlDateTime;
$ticket->save();
$user = $ticket->getUser();
if ($this->getConfig('notify_autoclose')) {
$et = Am_Mail_Template::load('helpdesk.notify_autoclose', $user->lang);
$et->setUser($user);
$et->setTicket($ticket);
$et->setUrl($this->getDi()->url('helpdesk/ticket/'.$ticket->ticket_mask,null,false,true));
$et->send($user);
}
}
}
}
function onInitFinished()
{
$this->getDi()->blocks->add(new Am_Block('member/main/top', null, 'helpdesk-notification', null, array($this, 'renderNotification')));
$this->getDi()->register('helpdeskStrategy', 'Am_Helpdesk_Strategy_Abstract')
->setConstructor('create')
->setArguments(array($this->getDi()));
$router = $this->getDi()->router;;
$router->addRoute('helpdesk-item', new Am_Mvc_Router_Route(
'helpdesk/faq/i/:title', array(
'module' => 'helpdesk',
'controller' => 'faq',
'action' => 'item'
)
));
$router->addRoute('helpdesk-category', new Am_Mvc_Router_Route(
'helpdesk/faq/c/:cat', array(
'module' => 'helpdesk',
'controller' => 'faq',
'action' => 'index'
)
));
$router->addRoute('helpdesk-ticket', new Am_Mvc_Router_Route(
'helpdesk/ticket/:ticket', array(
'module' => 'helpdesk',
'controller' => 'index',
'action' => 'view',
'page_id' => 'view'
)
));
$router->addRoute('helpdesk-ticket-admin', new Am_Mvc_Router_Route(
'helpdesk/admin/ticket/:ticket', array(
'module' => 'helpdesk',
'controller' => 'admin',
'action' => 'view',
'page_id' => 'view'
)
));
$router->addRoute('helpdesk-new', new Am_Mvc_Router_Route(
'helpdesk/ticket/new', array(
'module' => 'helpdesk',
'controller' => 'index',
'action' => 'new',
'page_id' => 'view'
)
));
$router->addRoute('helpdesk-new-admin', new Am_Mvc_Router_Route(
'helpdesk/admin/ticket/new', array(
'module' => 'helpdesk',
'controller' => 'admin',
'action' => 'new',
'page_id' => 'view'
)
));
}
function onBuildDemo(Am_Event $event)
{
$subjects = array(
'Please help',
'Urgent question',
'I have a problem',
'Important question',
'Pre-sale inquiry',
);
$questions = array(
"My website is now working. Can you help?",
"I have a problem with website script.\nWhere can I find documentation?",
"I am unable to place an order, my credit card is not accepted.",
);
$answers = array(
"Please call us to phone# 1-800-222-3334",
"We are looking to your problem, and it will be resolved within 4 hours",
);
$user = $event->getUser();
$now = $this->getDi()->time;
$added = amstrtotime($user->added);
/* @var $user User */
while (rand(0, 10) < 4) {
$created = min($now, $added + rand(60, $now - $added));
$ticket = $this->getDi()->helpdeskTicketRecord;
$ticket->status = HelpdeskTicket::STATUS_AWAITING_ADMIN_RESPONSE;
$ticket->subject = $subjects[rand(0, count($subjects) - 1)];
$ticket->user_id = $user->pk();
$ticket->created = sqlTime($created);
$ticket->updated = sqlTime($created);
$ticket->insert();
//
$msg = $this->getDi()->helpdeskMessageRecord;
$msg->content = $questions[rand(0, count($questions) - 1)];
$msg->type = 'message';
$msg->ticket_id = $ticket->pk();
$msg->dattm = sqlTime($created);
$msg->insert();
//
if (rand(0, 10) < 6) {
$msg = $this->getDi()->helpdeskMessageRecord;
$msg->content = $answers[rand(0, count($answers) - 1)];
$msg->type = 'message';
$msg->ticket_id = $ticket->pk();
$msg->dattm = sqlTime(min($created + rand(60, 3600 * 24), $now));
$msg->admin_id = $this->getDi()->adminTable->findFirstBy()->pk();
$msg->insert();
if (rand(0, 10) < 6)
$ticket->status = HelpdeskTicket::STATUS_AWAITING_USER_RESPONSE;
else
$ticket->status = HelpdeskTicket::STATUS_CLOSED;
$ticket->updated = $msg->dattm;
$ticket->update();
}
}
}
function onLoadReports()
{
require_once 'Am/Report/Helpdesk.php';
}
function onDbUpgrade(Am_Event $e)
{
if (version_compare($e->getVersion(), '4.2.20') < 0) {
echo "Fix FAQ categories...";
if (ob_get_level ())
ob_end_flush();
$this->getDi()->db->query("UPDATE ?_helpdesk_faq SET category=? WHERE category=?", null, '');
echo "Done \n";
echo "Add default Order to Helpdesk FAQ...";
$this->getDi()->db->query("SET @i = 0");
$this->getDi()->db->query("UPDATE ?_helpdesk_faq SET sort_order=(@i:=@i+1)");
echo "Done \n";
echo "Add default Order to Helpdesk Categories...";
$this->getDi()->db->query("SET @i = 0");
$this->getDi()->db->query("UPDATE ?_helpdesk_category SET sort_order=(@i:=@i+1)");
echo "Done \n";
}
if (version_compare($e->getVersion(), '5.0.5') <= 0) {
echo "Update Ticket Status...";
$this->getDi()->db->query("UPDATE ?_helpdesk_ticket SET has_new=1 WHERE status IN (?a)",
array(HelpdeskTicket::STATUS_AWAITING_USER_RESPONSE));
echo "Done \n";
}
if (version_compare($e->getVersion(), '5.1.6') <= 0) {
if (!$this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_resource_access WHERE resource_type=?", HelpdeskCategory::ACCESS_TYPE)) { //idempotent action
echo "Setup Default Protection for Categories...";
foreach($this->getDi()->helpdeskCategoryTable->findBy() as $cat) {
$this->getDi()->resourceAccessTable
->setAccess($cat->pk(), HelpdeskCategory::ACCESS_TYPE, array(
ResourceAccess::FN_FREE => array(
json_encode(array(
'start' => null,
'stop' => null,
'text' => ___('Free Access')
)))
));
}
echo "Done \n";
}
}
}
}PK \mJ$ helpdesk/module.xmlnu [
helpdesk
Helpdesk
Customer support helpdesk
5.0.6
PK \}0 . helpdesk/controllers/AdminFieldsController.phpnu [ hasPermission(Bootstrap_Helpdesk::ADMIN_PERM_CATEGORY);
}
protected function getTable()
{
return $this->getDi()->helpdeskTicketTable;
}
public function createGrid()
{
$grid = parent::createGrid();
$grid->addCallback(Am_Grid_Editable::CB_AFTER_DELETE, array($this, 'afterDelete'));
$grid->setPermissionId(Bootstrap_Helpdesk::ADMIN_PERM_CATEGORY);
return $grid;
}
public function createForm()
{
$form = new Am_Form_Admin_CustomField_Ticket($this->grid->getRecord());
$form->setTable($this->getTable());
return $form;
}
public function afterDelete($record)
{
foreach ($this->getDi()->helpdeskCategoryTable->findBy(array()) as $c) {
$fields = $c->unserializeList($c->fields);
if (in_array($record->name, $fields)) {
$fields = array_diff($fields, array($record->name));
$c->fields = $c->serializeList($fields);
$c->save();
}
}
}
}PK \LEE * helpdesk/controllers/AdminMyController.phpnu [ addWhere('t.owner_id=?d', Am_Di::getInstance()->authAdmin->getUserId());
$q->addWhere('t.status<>?', HelpdeskTicket::STATUS_CLOSED);
return $q;
}
public function getGridTitle()
{
return ___('Tickets Assigned to Me');
}
public function initGridFields()
{
parent::initGridFields();
$this->removeField('owner_id');
}
public function initActions()
{
parent::initActions();
$this->actionAdd(new Am_Grid_Action_Delete());
}
}
class Helpdesk_AdminMyController extends Am_Mvc_Controller_Pages
{
public function checkAdminPermissions(Admin $admin)
{
return $admin->hasPermission(Bootstrap_Helpdesk::ADMIN_PERM_ID);
}
function preDispatch()
{
$this->view->headLink()->appendStylesheet($this->view->_scriptCss('helpdesk-admin.css'));
$this->setActiveMenu('helpdesk-ticket-my');
parent::preDispatch();
}
public function initPages()
{
$this->addPage('Am_Helpdesk_Grid_My', 'index', ___('Tickets'))
->addPage(array($this, 'createController'), 'view', ___('Conversation'));
}
public function renderTabs()
{
return '';
}
public function createController($id, $title, $grid)
{
return new Am_Helpdesk_Controller($grid->getRequest(), $grid->getResponse(), $this->_invokeArgs);
}
}PK \'ʀ
&