diff --git a/include/ajax.thread.php b/include/ajax.thread.php index a66062e0b933607397803545f98c384d46b5b53c..0369548ed5deb1b855c6f2f9c3127d4eb9b4ff22 100644 --- a/include/ajax.thread.php +++ b/include/ajax.thread.php @@ -74,11 +74,11 @@ class ThreadAjaxAPI extends AjaxController { if (!$user_info) $info['error'] = __('Unable to find user in directory'); - return self::_addcollaborator($thread, null, $form, $info); + return self::_addcollaborator($thread, null, $form, 'addcc', $info); } //Collaborators utils - function addCollaborator($tid, $uid=0) { + function addCollaborator($tid, $type=null, $uid=0) { global $thisstaff; if (!($thread=Thread::lookup($tid)) @@ -90,7 +90,7 @@ class ThreadAjaxAPI extends AjaxController { //If not a post then assume new collaborator form if(!$_POST) - return self::_addcollaborator($thread, $user); + return self::_addcollaborator($thread, $user, null, $type); $user = $form = null; if (isset($_POST['id']) && $_POST['id']) { //Existing user/ @@ -107,7 +107,7 @@ class ThreadAjaxAPI extends AjaxController { array(), $errors))) { $info = array('msg' => sprintf(__('%s added as a collaborator'), Format::htmlchars($c->getName()))); - $c->setCc(); + $type == 'addbcc' ? $c->setBcc() : $c->setCc(); $c->save(); return self::_collaborators($thread, $info); } @@ -119,7 +119,7 @@ class ThreadAjaxAPI extends AjaxController { $info +=array('error' =>__('Unable to add collaborator.').' '.__('Internal error occurred')); } - return self::_addcollaborator($thread, $user, $form, $info); + return self::_addcollaborator($thread, $user, $form, $type, $info); } function updateCollaborator($tid, $cid) { @@ -194,15 +194,15 @@ class ThreadAjaxAPI extends AjaxController { return $resp; } - function _addcollaborator($thread, $user=null, $form=null, $info=array()) { + function _addcollaborator($thread, $user=null, $form=null, $type=null, $info=array()) { global $thisstaff; $info += array( 'title' => __('Add a collaborator'), - 'action' => sprintf('#thread/%d/add-collaborator', - $thread->getId()), - 'onselect' => sprintf('ajax.php/thread/%d/add-collaborator/', - $thread->getId()), + 'action' => sprintf('#thread/%d/add-collaborator/%s', + $thread->getId(), $type), + 'onselect' => sprintf('ajax.php/thread/%d/add-collaborator/%s/', + $thread->getId(), $type), ); ob_start(); diff --git a/include/class.filter.php b/include/class.filter.php index e76b5175a3d8b5c6ac4a866bdd091fe6ec045a04..1827342284a3bab796bc1db2244dd53c527e0e0b 100644 --- a/include/class.filter.php +++ b/include/class.filter.php @@ -471,24 +471,28 @@ class Filter { } function save($id,$vars,&$errors) { + //get current filter actions (they're validated before saving) + self::save_actions($id, $vars, $errors); + if ($this) { foreach ($this->getActions() as $A) { + $config = JsonDataParser::parse($A->configuration); if ($A->type == 'dept') { - $dept = Dept::lookup($A->parseConfiguration($vars)['dept_id']); + $dept = Dept::lookup($config['dept_id']); $dept_action = $A->getId(); } if ($A->type == 'topic') { - $topic = Topic::lookup($A->parseConfiguration($vars)['topic_id']); + $topic = Topic::lookup($config['topic_id']); $topic_action = $A->getId(); } } } - if($dept && !$dept->isActive() && !in_array('D' . $dept_action,$vars['actions'])) + if($dept && !$dept->isActive() && (is_array($vars['actions']) && !in_array('D' . $dept_action,$vars['actions']))) $errors['err'] = sprintf(__('%s selected for %s must be active'), __('Department'), __('Filter Action')); - if($topic && !$topic->isActive() && !in_array('D' . $topic_action,$vars['actions'])) + if($topic && !$topic->isActive() && (is_array($vars['actions']) && !in_array('D' . $topic_action,$vars['actions']))) $errors['err'] = sprintf(__('%s selected for %s must be active'), __('Help Topic'), __('Filter Action')); if(!$vars['execorder']) @@ -547,7 +551,6 @@ class Filter { # Don't care about errors stashed in $xerrors $xerrors = array(); self::save_rules($id,$vars,$xerrors); - self::save_actions($id, $vars, $errors); return count($errors) == 0; } @@ -555,20 +558,31 @@ class Filter { function validate_actions($action) { $errors = array(); $config = json_decode($action->ht['configuration'], true); - if ($action->ht['type'] == 'dept') { - $dept = Dept::lookup($config['dept_id']); - if (!$dept || !$dept->isActive()) { - $errors['err'] = sprintf(__('Unable to save: Please choose an active %s'), 'Department'); - return $errors; - } - } + switch ($action->ht['type']) { + case 'dept': + $dept = Dept::lookup($config['dept_id']); + if (!$dept || !$dept->isActive()) { + $errors['err'] = sprintf(__('Unable to save: Please choose an active %s'), 'Department'); + return $errors; + } + break; - if ($action->ht['type'] == 'topic') { - $topic = Topic::lookup($config['topic_id']); - if (!$topic || !$topic->isActive()) { - $errors['err'] = sprintf(__('Unable to save: Please choose an active %s'), 'Help Topic'); - return $errors; - } + case 'topic': + $topic = Topic::lookup($config['topic_id']); + if (!$topic || !$topic->isActive()) { + $errors['err'] = sprintf(__('Unable to save: Please choose an active %s'), 'Help Topic'); + return $errors; + } + break; + + default: + foreach ($config as $key => $value) { + if (!$value) { + $errors['err'] = sprintf(__('Unable to save: Please insert a value for %s'), ucfirst($action->ht['type'])); + return $errors; + } + } + break; } return false; @@ -597,7 +611,6 @@ class Filter { 'sort' => (int) $sort, )); $I->setConfiguration($errors, $vars); - $config = json_decode($I->ht['configuration'], true); $invalid = self::validate_actions($I); if ($invalid) { @@ -611,8 +624,6 @@ class Filter { if ($I = FilterAction::lookup($info)) { $I->setConfiguration($errors, $vars); - $config = json_decode($I->ht['configuration'], true); - $invalid = self::validate_actions($I); if ($invalid) { $errors['err'] = sprintf($invalid['err']); diff --git a/include/class.report.php b/include/class.report.php index 5e1ac94b97f52c3c8b5f5efb50ffa06e841c3737..c39ec47cc5ea595aaddcaf46d25323929d58c1cc 100644 --- a/include/class.report.php +++ b/include/class.report.php @@ -211,7 +211,7 @@ class OverviewReport { $headers = array(__('Help Topic')); $header = function($row) { return Topic::getLocalNameById($row['topic_id'], $row['topic__topic']); }; $pk = 'topic_id'; - $topics = Topic::getHelpTopics(); + $topics = Topic::getHelpTopics(false, Topic::DISPLAY_DISABLED); $stats = $stats ->values('topic_id', 'topic__topic', 'topic__flags') ->filter(array('dept_id__in' => $thisstaff->getDepts(), 'topic_id__gt' => 0, 'topic_id__in' => array_keys($topics))); diff --git a/include/class.thread.php b/include/class.thread.php index dd10d3a0d326235954f7be5066ccdb5ec182e8c3..017d7db353c3fbd5740935138f2fc26222a03dcb 100644 --- a/include/class.thread.php +++ b/include/class.thread.php @@ -299,12 +299,12 @@ implements Searchable { return false; // Referred to staff's department - if ($to->getDepts() && $this->referrals->findFirst(array( + if ($to->getDepts() && $this->referrals->filter(array( 'object_id__in' => $to->getDepts(), 'object_type' => ObjectModel::OBJECT_TYPE_DEPT))) return true; // Referred to staff's team - if ($to->getTeams() && $this->referrals->findFirst(array( + if ($to->getTeams() && $this->referrals->filter(array( 'object_id__in' => $to->getTeams(), 'object_type' => ObjectModel::OBJECT_TYPE_TEAM))) return true; @@ -778,6 +778,18 @@ implements TemplateVariable { ), ); + // Thread entry types + static protected $types = array( + 'M' => 'message', + 'R' => 'response', + 'N' => 'note', + 'B' => 'bccmessage', + ); + + function getTypeName() { + return self::$types[$this->type]; + } + function postEmail($mailinfo) { global $ost; @@ -1720,6 +1732,10 @@ implements TemplateVariable { static function getPermissions() { return self::$perms; } + + static function getTypes() { + return self::$types; + } } RolePermission::register(/* @trans */ 'Tickets', ThreadEntry::getPermissions()); diff --git a/include/class.ticket.php b/include/class.ticket.php index a1147c2cbb29115766bfe4279cc9d98aef31c97f..167703aaf49e2d1ae32d405f33210892b29b548c 100644 --- a/include/class.ticket.php +++ b/include/class.ticket.php @@ -207,9 +207,8 @@ implements RestrictedAccess, Threadable, Searchable { } function isReopenable() { - return ($this->getStatus()->isReopenable() - && $this->getDept()->allowsReopen() - && $this->getTopic()->allowsReopen()); + return ($this->getStatus()->isReopenable() && $this->getDept()->allowsReopen() + && ($this->getTopic() ? $this->getTopic()->allowsReopen() : null)); } function isClosed() { @@ -968,7 +967,7 @@ implements RestrictedAccess, Threadable, Searchable { 'name' => "{$fid}_id", 'label' => __('Help Topic'), 'default' => $this->getTopicId(), - 'choices' => Topic::getHelpTopics() + 'choices' => Topic::getHelpTopics(false, Topic::DISPLAY_DISABLED) )); break; case 'source': @@ -1649,10 +1648,18 @@ implements RestrictedAccess, Threadable, Searchable { $collaborators['cc'] = $collaborators; //collaborator email sent out - if ($collaborators['cc']) { + if ($collaborators['cc'] || $owner_recip) { //say dear collaborator if the ticket user is not a recipient - if (!$owner_recip) - $cnotice = $this->replaceVars($msg, array('recipient.name.first' => __('Collaborator'), 'recipient' => $recipient)); + if (!$owner_recip) { + $nameFormats = array_keys(PersonsName::allFormats()); + $names = array(); + foreach ($nameFormats as $key => $value) { + $names['recipient.name.' . $value] = __('Collaborator'); + } + $names = array_merge($names, array('recipient' => $recipient)); + $cnotice = $this->replaceVars($msg, $names); + } + //otherwise address email to ticket user else $cnotice = $this->replaceVars($msg, array('recipient' => $owner)); @@ -2971,7 +2978,7 @@ implements RestrictedAccess, Threadable, Searchable { $collabsCc = array(); if ($vars['ccs'] && $vars['emailcollab']) { $collabsCc[] = Collaborator::getCollabList($vars['ccs']); - $collabsCc['cc'] = $collabsCc; + $collabsCc['cc'] = $collabsCc[0]; } $email->send($user, $msg['subj'], $msg['body'], $attachments, @@ -2986,10 +2993,9 @@ implements RestrictedAccess, Threadable, Searchable { if (!($recipient = User::lookup($uid))) continue; - $msg = $this->replaceVars($bccmsg->asArray(), $variables + array( - 'recipient' => $user, - 'recipient.name.first' => - $recipient->getName()->getFirst())); + $extraVars = UsersName::getNameFormats($recipient, 'recipient'); + $extraVars = array_merge($extraVars, array('recipient' => $user)); + $msg = $this->replaceVars($bccmsg->asArray(), $variables + $extraVars); $email->send($recipient, $msg['subj'], $msg['body'], $attachments, $options); } @@ -4130,15 +4136,13 @@ implements RestrictedAccess, Threadable, Searchable { && ($bccmsg=$tpl->getNewTicketNoticeMsgTemplate()) && ($email=$dept->getEmail()) ) - $bccmsg = $ticket->replaceVars($bccmsg->asArray(), - array( - 'message' => $message, - 'signature' => $signature, - 'response' => ($response) ? $response->getBody() : '', - 'recipient' => $ticket->getOwner(), - 'recipient.name.first' => $recipient->getName()->getFirst(), - ) - ); + $extraVars = UsersName::getNameFormats($recipient, 'recipient'); + $extraVars = array_merge($extraVars, array( + 'message' => $message, + 'signature' => $signature, + 'response' => ($response) ? $response->getBody() : '', + 'recipient' => $ticket->getOwner())); + $bccmsg = $ticket->replaceVars($bccmsg->asArray(), $extraVars); $email->send($recipient, $bccmsg['subj'], $bccmsg['body'], $attachments, $options); diff --git a/include/class.user.php b/include/class.user.php index dcd04b9c5d59f2bc6c02f4e54c8e928a26c647d5..083e0d5bf2b1853e82d6804a53641d353dbf8fd9 100644 --- a/include/class.user.php +++ b/include/class.user.php @@ -813,6 +813,16 @@ implements TemplateVariable { return $this; } + function getNameFormats($user, $type) { + $nameFormats = array(); + + foreach (PersonsName::allFormats() as $format => $func) { + $nameFormats[$type . '.name.' . $format] = $user->getName()->$func[1](); + } + + return $nameFormats; + } + function asVar() { return $this->__toString(); } diff --git a/include/client/templates/thread-entry.tmpl.php b/include/client/templates/thread-entry.tmpl.php index ad9f3dc9fa33282b4a9bec980cc7daf2ee9fc7fc..e49b3b0389bf1c9d2f7c330ebac9039b536c0fc9 100644 --- a/include/client/templates/thread-entry.tmpl.php +++ b/include/client/templates/thread-entry.tmpl.php @@ -1,6 +1,6 @@ <?php global $cfg; -$entryTypes = array('M'=>'message', 'R'=>'response', 'N'=>'note', 'B' => 'bccmessage'); +$entryTypes = ThreadEntry::getTypes(); $user = $entry->getUser() ?: $entry->getStaff(); if ($entry->staff && $cfg->hideStaffName()) $name = __('Staff'); @@ -11,13 +11,14 @@ if ($cfg->isAvatarsEnabled() && $user) $avatar = $user->getAvatar(); ?> <?php - if ($entryTypes[$entry->type] == 'note') { - $entryTypes[$entry->type] = 'bccmessage'; +$type = $entryTypes[$entry->type]; +if ($type == 'note') { + $type = 'bccmessage'; $entry->type = 'B'; - } +} ?> -<div class="thread-entry <?php echo $entryTypes[$entry->type]; ?> <?php if ($avatar) echo 'avatar'; ?>"> +<div class="thread-entry <?php echo $type; ?> <?php if ($avatar) echo 'avatar'; ?>"> <?php if ($avatar) { ?> <span class="<?php echo ($entry->type == 'M' || $entry->type == 'B') ? 'pull-left' : 'pull-right'; ?> avatar"> <?php echo $avatar; ?> diff --git a/include/staff/filter.inc.php b/include/staff/filter.inc.php index 100e1273cb9def31eef2bc386705526e5fddb117..5816b4bf388cb147566688be145c9d5f8d72e6c8 100644 --- a/include/staff/filter.inc.php +++ b/include/staff/filter.inc.php @@ -240,17 +240,16 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info); if ($filter) { foreach ($filter->getActions() as $A) { $_warn = ''; $existing[] = $A->type; + $config = JsonDataParser::parse($A->configuration); if($A->type == 'dept') { $errors['topic_id'] = ''; - $dept_config = $A->parseConfiguration($_POST); - $dept = Dept::lookup($dept_config['dept_id']); + $dept = Dept::lookup($config['dept_id']); if($dept && !$dept->isActive()) $_warn = sprintf(__('%s must be active'), __('Department')); } elseif($A->type == 'topic') { $errors['dept_id'] = ''; - $topic_config = $A->parseConfiguration($_POST); - $topic = Topic::lookup($topic_config['topic_id']); + $topic = Topic::lookup($config['topic_id']); if($topic && !$topic->isActive()) $_warn = sprintf(__('%s must be active'), __('Help Topic')); } diff --git a/include/staff/templates/collaborators.tmpl.php b/include/staff/templates/collaborators.tmpl.php index 7f80a5804053f2c9b9ecf23d9880f4d5555f7b75..1a50164f1f78421050098dfef38f89de93d9cf0b 100644 --- a/include/staff/templates/collaborators.tmpl.php +++ b/include/staff/templates/collaborators.tmpl.php @@ -65,7 +65,7 @@ if(($users=$thread->getCollaborators())) {?> ?> <td> <div><a class="collaborator" id="addcollaborator" - href="#thread/<?php echo $thread->getId(); ?>/add-collaborator" + href="#thread/<?php echo $thread->getId(); ?>/add-collaborator/addcc" ><i class="icon-plus-sign"></i> <?php echo __('Add Collaborator'); ?></a></div> </td> </table> diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php index dd351122439b1d657e8c2aa96e982b828266036d..b5ededef80a34f4bd784568e908c2edf1b8ef8fe 100644 --- a/include/staff/ticket-view.inc.php +++ b/include/staff/ticket-view.inc.php @@ -1197,7 +1197,7 @@ $(function() { if(el.val().includes("NEW")) { $("li[title='— Add New —']").remove(); - var url = 'ajax.php/thread/' + tid + '/add-collaborator' ; + var url = 'ajax.php/thread/' + tid + '/add-collaborator/' + addTo ; $.userLookup(url, function(user) { e.preventDefault(); if($('.dialog#confirm-action').length) { diff --git a/scp/ajax.php b/scp/ajax.php index c746da68d0650c46ce0b524f789803e70d6b1582..85d010e92b48b47d39643715bd8d9884c4c040c8 100644 --- a/scp/ajax.php +++ b/scp/ajax.php @@ -211,9 +211,9 @@ $dispatcher = patterns('', url_get('^(?P<tid>\d+)/collaborators/preview$', 'previewCollaborators'), url_get('^(?P<tid>\d+)/collaborators$', 'showCollaborators'), url_post('^(?P<tid>\d+)/collaborators$', 'updateCollaborators'), - url_get('^(?P<tid>\d+)/add-collaborator/(?P<uid>\d+)$', 'addCollaborator'), + url_get('^(?P<tid>\d+)/add-collaborator/(?P<type>\w+)/(?P<uid>\d+)$', 'addCollaborator'), url_get('^(?P<tid>\d+)/add-collaborator/auth:(?P<bk>\w+):(?P<id>.+)$', 'addRemoteCollaborator'), - url('^(?P<tid>\d+)/add-collaborator$', 'addCollaborator'), + url('^(?P<tid>\d+)/add-collaborator/(?P<type>\w+)$', 'addCollaborator'), url_get('^(?P<tid>\d+)/collaborators/(?P<cid>\d+)/view$', 'viewCollaborator'), url_post('^(?P<tid>\d+)/collaborators/(?P<cid>\d+)$', 'updateCollaborator') )), diff --git a/scp/filters.php b/scp/filters.php index 23bbe23e37ae0721eccbf43288dbfc6a77ab0e75..c83f9eac074175b908b3cea6cf3eaaa75778f64a 100644 --- a/scp/filters.php +++ b/scp/filters.php @@ -120,11 +120,12 @@ $tip_namespace = 'manage.filter'; if($filter || ($_REQUEST['a'] && !strcasecmp($_REQUEST['a'],'add'))) { if($filter) { foreach ($filter->getActions() as $A) { + $config = JsonDataParser::parse($A->configuration); if($A->type == 'dept') - $dept = Dept::lookup($A->parseConfiguration($_POST)['dept_id']); + $dept = Dept::lookup($config['dept_id']); if($A->type == 'topic') - $topic = Topic::lookup($A->parseConfiguration($_POST)['topic_id']); + $topic = Topic::lookup($config['topic_id']); } }