Newer
Older
'visibility' => new VisibilityConstraint(
new Q(array('state__eq'=>'closed')),
VisibilityConstraint::HIDDEN
),
)),
'reopenstatus' => new ChoiceField(array(
'label' => __('Reopen Status'),
'required' => false,
'default' => isset($source['reopenstatus'])
? $source['reopenstatus'] : 0,
'id' => 'reopenstatus',
'name' => 'reopenstatus',
'choices' => $status_choices,
'configuration' => array(
'widget' => 'dropdown',
'multiselect' =>false
),
'visibility' => new VisibilityConstraint(
new Q(array('allowreopen__eq'=> true)),
VisibilityConstraint::HIDDEN
),
))
);
}
function getConfigurationForm($source=null) {
if (!($form = $this->getForm()))
return null;
$form = $form->getForm($source);
$fields = $form->getFields();
foreach ($fields as $k => $f) {
if ($f->get('name') == 'state' //TODO: check if editable.
&& ($extras=$this->getExtraConfigOptions($source))) {
foreach ($extras as $extra) {
$extra->setForm($form);
$fields->insert(++$k, $extra);
if (!isset($f->ht['editable']))
$f->ht['editable'] = true;
// Enable selection and display of private states
$form->getField('state')->options['private_too'] = true;
return $form;
}
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
function getListItemBasicForm($source=null, $item=false) {
return new SimpleForm(array(
'name' => new TextboxField(array(
'required' => true,
'label' => __('Value'),
'configuration' => array(
'translatable' => $item ? $item->getTranslateTag('value') : false,
'size' => 60,
'length' => 0,
'autofocus' => true,
),
)),
'extra' => new TextboxField(array(
'label' => __('Abbreviation'),
'configuration' => array(
'size' => 60,
'length' => 0,
),
)),
), $source);
}
function getSummaryFields() {
// Like the main one, except the description and state fields are
// welcome on the screen
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
foreach ($this->getConfigurationForm()->getFields() as $f) {
if (in_array($f->get('type'), array('state', 'text', 'datetime', 'phone')))
$prop_fields[] = $f;
elseif (strpos($f->get('type'), 'list-') === 0)
$prop_fields[] = $f;
elseif ($f->get('name') == 'description')
$prop_fields[] = $f;
// 4 property columns max
if (count($prop_fields) == 4)
break;
}
return $prop_fields;
}
}
CustomListHandler::register('ticket-status', 'TicketStatusList');
class TicketStatus
extends VerySimpleModel
implements CustomListItem, TemplateVariable {
static $meta = array(
'table' => TICKET_STATUS_TABLE,
'ordering' => array('name'),
'pk' => array('id'),
'joins' => array(
'tickets' => array(
'reverse' => 'TicketModel.status',
)
)
);
var $_list;
var $_form;
var $_settings;
var $_properties;
const ENABLED = 0x0001;
const INTERNAL = 0x0002; // Forbid deletion or name and status change.
protected function hasFlag($field, $flag) {
return 0 !== ($this->get($field) & $flag);
}
protected function clearFlag($field, $flag) {
return $this->set($field, $this->get($field) & ~$flag);
}
protected function setFlag($field, $flag) {
return $this->set($field, $this->get($field) | $flag);
}
return ($this->get('properties'));
}
function isEnabled() {
return $this->hasFlag('mode', self::ENABLED);
}
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
function isReopenable() {
if (strcasecmp($this->get('state'), 'closed'))
return true;
if (($c=$this->getConfiguration())
&& $c['allowreopen']
&& isset($c['reopenstatus']))
return true;
return false;
}
function getReopenStatus() {
global $cfg;
$status = null;
if ($this->isReopenable()
&& ($c = $this->getConfiguration())
&& isset($c['reopenstatus']))
$status = TicketStatus::lookup(
$c['reopenstatus'] ?: $cfg->getDefaultTicketStatusId());
return ($status
&& !strcasecmp($status->getState(), 'open'))
? $status : null;
}
function enable() {
// Ticket status without properties cannot be enabled!
if (!$this->isEnableable())
return false;
return $this->setFlag('mode', self::ENABLED);
}
function disable() {
return (!$this->isInternal()
&& $this->clearFlag('mode', self::ENABLED));
}
function isDefault() {
global $cfg;
return ($cfg
&& $cfg->getDefaultTicketStatusId() == $this->getId());
}
return ($this->getState());
function isDisableable() {
return !($this->isInternal() || $this->isDefault());
}
return !($this->isInternal()
|| $this->isDefault()
|| $this->getNumTickets());
return ($this->isDefault()
|| $this->hasFlag('mode', self::INTERNAL));
}
function getNumTickets() {
return $this->tickets->count();
}
function getId() {
return $this->get('id');
}
function getName() {
return $this->get('name');
}
function getState() {
return $this->get('state');
}
function getValue() {
return $this->getName();
}
function getAbbrev() {
return '';
}
function getSortOrder() {
return $this->get('sort');
}
private function getProperties() {
if (!isset($this->_properties)) {
$this->_properties = $this->get('properties');
if (is_string($this->_properties))
$this->_properties = JsonDataParser::parse($this->_properties);
elseif (!$this->_properties)
$this->_properties = array();
}
return $this->_properties;
}
function getTranslateTag($subtag) {
return _H(sprintf('status.%s.%s', $subtag, $this->id));
}
$tag = $this->getTranslateTag($subtag);
$T = CustomDataTranslation::translate($tag);
static function getLocalById($id, $subtag, $default) {
$tag = _H(sprintf('status.%s.%s', $subtag, $id));
$T = CustomDataTranslation::translate($tag);
return $T != $tag ? $T : $default;
}
// TemplateVariable interface
static function getVarScope() {
$base = array(
'name' => __('Status label'),
'state' => __('State name (e.g. open or closed)'),
);
return $base;
}
function getList() {
if (!isset($this->_list))
$this->_list = DynamicList::lookup(array('type' => 'ticket-status'));
return $this->_list;
}
function getListId() {
if (($list = $this->getList()))
return $list->getId();
}
function getConfigurationForm($source=null) {
if (!$this->_form) {
$config = $this->getConfiguration();
// Forcefully retain state for internal statuses
if ($source && $this->isInternal())
$source['state'] = $this->getState();
$this->_form = $this->getList()->getConfigurationForm($source);
if (!$source && $config) {
$fields = $this->_form->getFields();
foreach ($fields as $f) {
$val = $config[$f->get('id')] ?: $config[$f->get('name')];
if (isset($val))
$f->value = $f->to_php($val);
elseif ($f->get('default'))
$f->value = $f->get('default');
}
}
if ($this->isInternal()
&& ($f=$this->_form->getField('state'))) {
$f->ht['required'] = $f->ht['editable'] = false;
}
return $this->_form;
}
function getFields() {
return $this->getConfigurationForm()->getFields();
}
function getConfiguration() {
if (!$this->_settings) {
$this->_settings = $this->getProperties();
if (!$this->_settings)
$this->_settings = array();
if ($form = $this->getList()->getForm()) {
foreach ($form->getFields() as $f) {
$name = mb_strtolower($f->get('name'));
$id = $f->get('id');
switch($name) {
case 'flags':
foreach (TicketFlagField::$_flags as $k => $v)
$this->_settings[$id][$k] = $v['name'];
$this->_settings[$id][$this->get('state')] = $this->get('state');
break;
default:
if (!$this->_settings[$id] && $this->_settings[$name])
$this->_settings[$id] = $this->_settings[$name];
}
}
}
}
return $this->_settings;
}
function setConfiguration($vars, &$errors=array()) {
foreach ($this->getConfigurationForm($vars)->getFields() as $f) {
// Only bother with editable fields
if (!$f->isEditable()) continue;
$errors = array_merge($errors, $f->errors());
if ($f->errors()) continue;
$name = mb_strtolower($f->get('name'));
switch ($name) {
case 'flags':
if ($val && is_array($val)) {
$flags = 0;
foreach ($val as $k => $v) {
if (isset(TicketFlagField::$_flags[$k]))
$flags += TicketFlagField::$_flags[$k]['flag'];
$f->addError(__('Unknown or invalid flag'), $name);
}
$this->set('flags', $flags);
} elseif ($val && !$f->errors()) {
$f->addError(__('Unknown or invalid flag format'), $name);
// Internal statuses cannot change state
if ($this->isInternal())
break;
if ($val)
$this->set('state', $val);
$f->addError(__('Unknown or invalid state'), $name);
break;
default: //Custom properties the user might add.
// Add field specific validation errors (warnings)
$errors = array_merge($errors, $f->errors());
}
if (count($errors) === 0) {
if ($properties && is_array($properties))
$properties = JsonDataEncoder::encode($properties);
$this->set('properties', $properties);
$this->save(true);
}
return count($errors) === 0;
}
function display() {
return sprintf('<a class="preview" href="#"
data-preview="#list/%d/items/%d/preview">%s</a>',
$this->getListId(),
$this->getId(),
$this->getLocalName()
);
}
$fields = array('name', 'sort');
foreach($fields as $k) {
$this->set($k, $vars[$k]);
// Statuses with tickets are not deletable
if (!$this->isDeletable())
return false;
static function create($ht=false) {
if (!is_array($ht))
return null;
if (!isset($ht['mode']))
$ht['mode'] = 1;
$ht['created'] = new SqlFunction('NOW');
return new static($ht);
static function lookup($var, $list=null) {
if (!($item = parent::lookup($var)))
return null;
$item->_list = $list;
return $item;
}
static function __create($ht, &$error=false) {
global $ost;
$ht['properties'] = JsonDataEncoder::encode($ht['properties']);
if (($status = TicketStatus::create($ht)))
$status->save(true);
return $status;
}
static function status_options() {
include(STAFFINC_DIR . 'templates/status-options.tmpl.php');
}
}