Newer
Older
function hasIdValue() {
return true;
}
function getChoices($verbose=false) {
return Topic::getHelpTopics(false, Topic::DISPLAY_DISABLED);
}
}
require_once INCLUDE_DIR . 'class.dept.php';
class DepartmentChoiceField extends AdvancedSearchSelectionField {
function getChoices($verbose=false) {
return Dept::getDepartments();
}
function getQuickFilterChoices() {
global $thisstaff;
if (!isset($this->_choices)) {
$this->_choices = array();
$depts = $thisstaff ? $thisstaff->getDepts() : array();
foreach ($this->getChoices() as $id => $name) {
if (!$depts || in_array($id, $depts))
$this->_choices[$id] = $name;
}
}
return $this->_choices;
function getSearchMethods() {
return array(
'includes' => __('is'),
'!includes' => __('is not'),
function addToQuery($query, $name=false) {
return $query->values('dept_id', 'dept__name');
}
function applyOrderBy($query, $reverse=false, $name=false) {
$reverse = $reverse ? '-' : '';
return $query->order_by("{$reverse}dept__name");
}
class AssigneeChoiceField extends ChoiceField {
function getChoices($verbose=false) {
global $thisstaff;
if (!isset($this->_items)) {
$items = array(
'M' => __('Me'),
'T' => __('One of my teams'),
);
foreach (Staff::getStaffMembers() as $id=>$name) {
// Don't include $thisstaff (since that's 'Me')
if ($thisstaff && $thisstaff->getId() == $id)
continue;
$items['s' . $id] = $name;
}
foreach (Team::getTeams() as $id=>$name) {
$items['t' . $id] = $name;
}
$this->_items = $items;
return $this->_items;
}
function getChoice($k) {
$choices = $this->getChoices();
return $choices[$k] ?: null;
}
function getSearchMethods() {
return array(
'assigned' => __('assigned'),
'!assigned' => __('unassigned'),
'includes' => __('includes'),
'!includes' => __('does not include'),
);
}
function getSearchMethodWidgets() {
return array(
'assigned' => null,
'!assigned' => null,
'includes' => array('ChoiceField', array(
'choices' => $this->getChoices(),
'configuration' => array('multiselect' => true),
)),
'!includes' => array('ChoiceField', array(
'choices' => $this->getChoices(),
'configuration' => array('multiselect' => true),
)),
);
}
function getSearchQ($method, $value, $name=false) {
global $thisstaff;
$Q = new Q();
switch ($method) {
case 'assigned':
$Q->negate();
case '!assigned':
$Q->add(array('team_id' => 0,
'staff_id' => 0));
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
break;
case '!includes':
$Q->negate();
case 'includes':
$teams = $agents = array();
foreach ($value as $id => $ST) {
switch ($id[0]) {
case 'M':
$agents[] = $thisstaff->getId();
break;
case 's':
$agents[] = (int) substr($id, 1);
break;
case 'T':
$teams = array_merge($thisstaff->getTeams());
break;
case 't':
$teams[] = (int) substr($id, 1);
break;
}
}
$constraints = array();
if ($teams)
$constraints['team_id__in'] = $teams;
if ($agents)
$constraints['staff_id__in'] = $agents;
$Q->add(Q::any($constraints));
}
return $Q;
}
function describeSearchMethod($method) {
switch ($method) {
case 'assigned':
return __('assigned');
case '!assigned':
return __('unassigned');
default:
return parent::describeSearchMethod($method);
}
}
function addToQuery($query, $name=false) {
$fields = array();
foreach(Staff::getsortby('staff__') as $key)
$fields[] = new SqlField($key);
$fields[] = new SqlField('team__name');
$fields[] = 'zzz';
$expr = call_user_func_array(array('SqlFunction', 'COALESCE'), $fields);
$query->annotate(array($name ?: 'assignee' => $expr));
return $query->values('staff__firstname', 'staff__lastname', 'team__name', 'team_id');
}
function from_query($row, $name=false) {
if ($row['staff__firstname'])
return new AgentsName(array('first' => $row['staff__firstname'], 'last' => $row['staff__lastname']));
if ($row['team_id'])
return Team::getLocalById($row['team_id'], 'name', $row['team__name']);
}
function display($value) {
return (string) $value;
}
function toString($value) {
if (!is_array($value))
$value = array($value => $value);
$selection = array();
foreach ($value as $k => $v)
$selection[] = $this->getChoice($k) ?: (string) $v;
return implode(', ', $selection);
}
class AssignedField extends AssigneeChoiceField {
function getSearchMethods() {
return array(
'assigned' => __('assigned'),
'!assigned' => __('unassigned'),
);
}
function addToQuery($query, $name=false) {
return $query->values('staff_id', 'team_id');
}
function from_query($row, $name=false) {
return ($row['staff_id'] || $row['staff_id'])
? __('Yes') : __('No');
}
}
/**
* Simple trait which changes the SQL for "has a value" and "does not have a
* value" to check for zero or non-zero. Useful for not nullable fields.
*/
trait ZeroMeansUnset {
function getSearchQ($method, $value, $name=false) {
$name = $name ?: $this->get('name');
switch ($method) {
// osTicket commonly uses `0` to represent an unset state, so
// the set and unset checks need to check for both not null and
// nonzero
case 'nset':
return new Q([$name => 0]);
case 'set':
return Q::not([$name => 0]);
}
return parent::getSearchQ($method, $value, $name);
}
}
class AgentSelectionField extends AdvancedSearchSelectionField {
function getChoices($verbose=false) {
return array('M' => __('Me')) + Staff::getStaffMembers();
function toString($value) {
$choices = $this->getChoices();
$selection = array();
foreach ($value as $k => $v)
if (isset($choices[$k]))
$selection[] = $choices[$k];
return $selection ? implode(',', $selection) :
parent::toString($value);
}
function getSearchQ($method, $value, $name=false) {
global $thisstaff;
// unpack me
if (isset($value['M']) && $thisstaff) {
$value[$thisstaff->getId()] = $thisstaff->getName();
unset($value['M']);
}
return parent::getSearchQ($method, $value, $name);
}
function getSortKeys($path='') {
return Staff::getsortby('staff__');
}
function applyOrderBy($query, $reverse=false, $name=false) {
$reverse = $reverse ? '-' : '';
return Staff::nsort($query, "{$reverse}staff__");
class DepartmentManagerSelectionField extends AgentSelectionField {
function getChoices($verbose=false) {
return Staff::getStaffMembers();
}
function getSearchQ($method, $value, $name=false) {
return parent::getSearchQ($method, $value, 'dept__manager_id');
}
}
class TeamSelectionField extends AdvancedSearchSelectionField {
function getChoices($verbose=false) {
return array('T' => __('One of my teams')) + Team::getTeams();
}
function getSearchQ($method, $value, $name=false) {
global $thisstaff;
// Unpack my teams
if (isset($value['T']) && $thisstaff
&& ($teams = $thisstaff->getTeams())) {
unset($value['T']);
$value = $value + array_flip($teams);
}
return parent::getSearchQ($method, $value, $name);
function getSortKeys() {
return array('team__name');
}
function applyOrderBy($query, $reverse=false, $name=false) {
$reverse = $reverse ? '-' : '';
return $query->order_by("{$reverse}team__name");
}
class TicketStateChoiceField extends AdvancedSearchSelectionField {
function getChoices($verbose=false) {
return array(
'open' => __('Open'),
'closed' => __('Closed'),
'archived' => _P('ticket state name', 'Archived'),
'deleted' => _P('ticket state name','Deleted'),
);
}
function getSearchMethods() {
return array(
'includes' => __('is'),
'!includes' => __('is not'),
);
}
function getSearchQ($method, $value, $name=false) {
return parent::getSearchQ($method, $value, 'status__state');
}
}
class TicketFlagChoiceField extends ChoiceField {
function getChoices($verbose=false) {
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
return array(
'isanswered' => __('Answered'),
'isoverdue' => __('Overdue'),
);
}
function getSearchMethods() {
return array(
'includes' => __('is'),
'!includes' => __('is not'),
);
}
function getSearchQ($method, $value, $name=false) {
$Q = new Q();
if (isset($value['isanswered']))
$Q->add(array('isanswered' => 1));
if (isset($value['isoverdue']))
$Q->add(array('isoverdue' => 1));
if ($method == '!includes')
$Q->negate();
if ($Q->constraints)
return $Q;
}
class TicketSourceChoiceField extends ChoiceField {
function getChoices($verbose=false) {
return Ticket::getSources();
}
function getSearchMethods() {
return array(
'includes' => __('is'),
'!includes' => __('is not'),
);
}
function getSearchQ($method, $value, $name=false) {
return parent::getSearchQ($method, $value, 'source');
}
}
class OpenClosedTicketStatusList extends TicketStatusList {
function getItems($criteria=array()) {
$rv = array();
$base = parent::getItems($criteria);
foreach ($base as $idx=>$S) {
if (in_array($S->state, array('open', 'closed')))
$rv[$idx] = $S;
}
return $rv;
}
}
class TicketStatusChoiceField extends SelectionField {
static $widget = 'ChoicesWidget';
function getList() {
return new OpenClosedTicketStatusList(
DynamicList::lookup(
array('type' => 'ticket-status'))
);
}
function getSearchMethods() {
return array(
'includes' => __('is'),
'!includes' => __('is not'),
function getSearchQ($method, $value, $name=false) {
$name = $name ?: $this->get('name');
switch ($method) {
case '!includes':
return Q::not(array("{$name}__in" => array_keys($value)));
case 'includes':
return new Q(array("{$name}__in" => array_keys($value)));
default:
return parent::getSearchQ($method, $value, $name);
}
}
interface Searchable {
// Fetch an array of [ orm__path => Field() ] pairs. The field label is
// used when this list is rendered in a dropdown, and the field search
// mechanisms are use to apply query filtering based on the field.
static function getSearchableFields();
// Determine if the object supports abritrary form additions, through
// the "Manage Forms" dialog usually
static function supportsCustomData();