Newer
Older
$timezone = new DateTimezone($config['timezone']);
$datetime->setTimezone($timezone);
}
$value = $this->format($datetime->format('U'),
$datetime->getTimezone()->getName());
// No need to show timezone
if (!$config['time'])
return $value;
// Display is NOT timezone aware show entry's timezone.
return sprintf('%s (%s)',
$value, $datetime->format('T'));
function from_query($row, $name=false) {
$value = parent::from_query($row, $name);
$timestamp = is_int($value) ? $value : (int) strtotime($value);
return ($timestamp > 0) ? $timestamp : '';
function format($timestamp, $timezone=false) {
if (!$timestamp || $timestamp <= 0)
return '';
$config = $this->getConfiguration();
if ($config['time'])
$formatted = Format::datetime($timestamp, false, $timezone);
else
$formatted = Format::date($timestamp, false, false, $timezone);
return $formatted;
$timestamp = is_int($value) ? $value : (int) strtotime($value);
if ($timestamp <= 0)
return '';
return $this->format($timestamp);
}
function asVar($value, $id=false) {
return null;
$datetime = $this->getDateTime($value);
$config = $this->getConfiguration();
if (!$config['gmt'] || !$config['time'])
$timezone = $datetime->getTimezone()->getName();
$timezone = false;
return new FormattedDate($value, array(
'timezone' => $timezone,
'format' => $config['time'] ? 'long' : 'short'
)
);
}
function asVarType() {
return 'FormattedDate';
function getConfigurationOptions() {
return array(
'time' => new BooleanField(array(
'id'=>1, 'label'=>__('Time'), 'required'=>false, 'default'=>false,
'desc'=>__('Show time selection with date picker')))),
'timezone' => new TimezoneField(array(
'id'=>2, 'label'=>__('Timezone'), 'required'=>false,
'hint'=>__('Timezone of the date time selection'),
'configuration' => array('autodetect'=>false,
'prompt' => __("User's timezone")),
'visibility' => new VisibilityConstraint(
new Q(array('time__eq'=> true)),
VisibilityConstraint::HIDDEN
),
)),
'id'=>3, 'label'=>__('Timezone Aware'), 'required'=>false,
'desc'=>__("Show date/time relative to user's timezone")))),
'id'=>4, 'label'=>__('Earliest'), 'required'=>false,
'hint'=>__('Earliest date selectable'))),
'id'=>5, 'label'=>__('Latest'), 'required'=>false,
'default'=>null, 'hint'=>__('Latest date selectable'))),
'id'=>6, 'label'=>__('Allow Future Dates'), 'required'=>false,
'desc'=>__('Allow entries into the future' /* Used in the date field */)),
)),
);
}
function validateEntry($value) {
$config = $this->getConfiguration();
parent::validateEntry($value);
if (!$value || !($datetime = Format::parseDateTime($value)))
$min = $this->getMinDateTime();
$max = $this->getMaxDateTime();
$this->_errors[] = __('Enter a valid date');
} elseif ($min and $val < $min) {
$this->_errors[] = sprintf('%s (%s)',
__('Selected date is earlier than permitted'),
Format::date($min->getTimestamp(), false, false,
$min->getTimezone()->getName() ?: 'UTC')
);
} elseif ($max and $val > $max) {
$this->_errors[] = sprintf('%s (%s)',
__('Selected date is later than permitted'),
Format::date($max->getTimestamp(), false, false,
$max->getTimezone()->getName() ?: 'UTC')
);
}
// SearchableField interface ------------------------------
function getSearchMethods() {
return array(
'set' => __('has a value'),
'nset' => __('does not have a value'),
'equal' => __('on'),
'before' => __('before'),
'after' => __('after'),
'between' => __('between'),
'ndaysago' => __('in the last n days'),
'ndays' => __('in the next n days'),
'future' => __('in the future'),
'past' => __('in the past'),
'distfut' => __('more than n days from now'),
'distpast' => __('more than n days ago'),
);
}
function getSearchMethodWidgets() {
$config_notime = $config = $this->getConfiguration();
$config_notime['time'] = false;
$nday_form = function() {
$intervals = array(
'i' => _N('minute', 'minutes', 5),
'h' => _N('hour', 'hours', 5),
'd' => _N('day','days', 5),
'w' => _N('week', 'weeks', 5),
'm' => _N('month', 'months', 5),
);
return array(
'until' => new TextboxField(array(
'configuration' => array('validator'=>'number', 'size'=>4))
),
'int' => new ChoiceField(array(
'default' => 'd',
'choices' => $intervals,
)),
);
};
return array(
'set' => null,
'past' => null,
'future' => null,
'equal' => array('DatetimeField', array(
'configuration' => $config_notime,
'nequal' => array('DatetimeField', array(
'configuration' => $config_notime,
)),
'before' => array('DatetimeField', array(
'configuration' => $config,
)),
'after' => array('DatetimeField', array(
'configuration' => $config,
)),
'between' => array('InlineformField', array(
'form' => array(
'left' => new DatetimeField(),
'text' => new FreeTextField(array(
'configuration' => array('content' => 'and'))
),
'right' => new DatetimeField(),
),
)),
'ndaysago' => array('InlineformField', array('form'=>$nday_form())),
'ndays' => array('InlineformField', array('form'=>$nday_form())),
'distfut' => array('InlineformField', array('form'=>$nday_form())),
'distpast' => array('InlineformField', array('form'=>$nday_form())),
);
}
function getSearchQ($method, $value, $name=false) {
static $intervals = array(
'm' => 'MONTH',
'w' => 'WEEK',
'd' => 'DAY',
'h' => 'HOUR',
'i' => 'MINUTE',
);
$name = $name ?: $this->get('name');
$now = SqlFunction::NOW();
$config = $this->getConfiguration();
if (is_int($value))
$value = DateTime::createFromFormat('U', !$config['gmt'] ? Misc::gmtime($value) : $value) ?: $value;
elseif (is_string($value))
$value = Format::parseDateTime($value) ?: $value;
case 'equal':
$l = clone $value;
$r = $value->add(new DateInterval('P1D'));
return new Q(array(
"{$name}__gte" => $l,
"{$name}__lt" => $r
));
case 'nequal':
$l = clone $value;
$r = $value->add(new DateInterval('P1D'));
return Q::any(array(
"{$name}__lt" => $l,
"{$name}__gte" => $r,
));
case 'future':
$value = $now;
case 'after':
return new Q(array("{$name}__gte" => $value));
case 'past':
$value = $now;
case 'before':
return new Q(array("{$name}__lt" => $value));
case 'between':
foreach (array('left', 'right') as $side) {
$value[$side] = is_int($value[$side])
? DateTime::createFromFormat('U', !$config['gmt']
? Misc::gmtime($value[$side]) : $value[$side]) ?: $value[$side]
return new Q(array(
"{$name}__gte" => $value['left'],
"{$name}__lte" => $value['right'],
));
case 'ndaysago':
$int = $intervals[$value['int'] ?: 'd'] ?: 'DAY';
$interval = new SqlInterval($int, $value['until']);
"{$name}__range" => array($now->minus($interval), $now),
));
case 'ndays':
$int = $intervals[$value['int'] ?: 'd'] ?: 'DAY';
$interval = new SqlInterval($int, $value['until']);
"{$name}__range" => array($now, $now->plus($interval)),
));
// Distant past and future ranges
case 'distpast':
$int = $intervals[$value['int'] ?: 'd'] ?: 'DAY';
$interval = new SqlInterval($int, $value['until']);
return new Q(array(
"{$name}__lte" => $now->minus($interval),
));
case 'distfut':
$int = $intervals[$value['int'] ?: 'd'] ?: 'DAY';
$interval = new SqlInterval($int, $value['until']);
return new Q(array(
"{$name}__gte" => $now->plus($interval),
));
default:
return parent::getSearchQ($method, $value, $name);
}
}
function describeSearchMethod($method) {
switch ($method) {
case 'before':
return __('%1$s before %2$s' /* occurs before a date and time */);
case 'after':
return __('%1$s after %2$s' /* occurs after a date and time */);
case 'ndays':
return __('%1$s in the next %2$s' /* occurs within a window (like 3 days) */);
case 'ndaysago':
return __('%1$s in the last %2$s' /* occurs within a recent window (like 3 days) */);
case 'distfut':
return __('%1$s after %2$s from now' /* occurs after a window (like 3 days) */);
case 'distpast':
return __('%1$s before %2$s ago' /* occurs previous to a window (like 3 days) */);
case 'between':
return __('%1$s between %2$s and %3$s');
case 'future':
return __('%1$s is in the future');
case 'past':
return __('%1$s is in the past');
default:
return parent::describeSearchMethod($method);
}
}
function describeSearch($method, $value, $name=false) {
if ($method === 'between') {
$l = $this->toString($value['left']);
$r = $this->toString($value['right']);
$desc = $this->describeSearchMethod($method);
return sprintf($desc, $name, $l, $r);
}
return parent::describeSearch($method, $value, $name);
}
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
function supportsQuickFilter() {
return true;
}
function getQuickFilterChoices() {
return array(
'h' => __('Today'),
'm' => __('Tomorrow'),
'g' => __('Yesterday'),
'l7' => __('Last 7 days'),
'l30' => __('Last 30 days'),
'n7' => __('Next 7 days'),
'n30' => __('Next 30 days'),
/* Ugh. These boundaries are so difficult in SQL
'w' => __('This Week'),
'm' => __('This Month'),
'lw' => __('Last Week'),
'lm' => __('Last Month'),
'nw' => __('Next Week'),
'nm' => __('Next Month'),
*/
);
}
function applyQuickFilter($query, $qf_value, $name=false) {
$name = $name ?: $this->get('name');
$now = SqlFunction::NOW();
$midnight = Misc::dbtime(time() - (time() % 86400));
switch ($qf_value) {
case 'l7':
return $query->filter([
"{$name}__range" => array($now->minus(SqlInterval::DAY(7)), $now),
]);
case 'l30':
return $query->filter([
"{$name}__range" => array($now->minus(SqlInterval::DAY(30)), $now),
]);
case 'n7':
return $query->filter([
"{$name}__range" => array($now, $now->minus(SqlInterval::DAY(7))),
]);
case 'n30':
return $query->filter([
"{$name}__range" => array($now, $now->minus(SqlInterval::DAY(30))),
]);
case 'g':
$midnight -= 86400;
// Fall through to the today case
case 'm':
if ($qf_value === 'm') $midnight += 86400;
// Fall through to the today case
case 'h':
$midnight = DateTime::createFromFormat('U', $midnight);
return $query->filter([
"{$name}__range" => array($midnight,
SqlExpression::plus($midnight, SqlInterval::DAY(1))),
]);
}
}
/**
* This is kind-of a special field that doesn't have any data. It's used as
* a field to provide a horizontal section break in the display of a form
*/
class SectionBreakField extends FormField {
static $widget = 'SectionBreakWidget';
function hasData() {
return false;
}
function isBlockLevel() {
return true;
}
}
class ThreadEntryField extends FormField {
static $widget = 'ThreadEntryWidget';
function isChangeable() {
return false;
}
function isBlockLevel() {
return true;
}
function isPresentationOnly() {
return true;
}
function getMedia() {
$config = $this->getConfiguration();
$media = parent::getMedia() ?: array();
if ($config['attachments'])
$media = array_merge_recursive($media, FileUploadWidget::$media);
return $media;
}
function getConfiguration() {
global $cfg;
$config = parent::getConfiguration();
$config['html'] = (bool) ($cfg && $cfg->isRichTextEnabled());
function getConfigurationOptions() {
global $cfg;
$attachments = new FileUploadField();
$fileupload_config = $attachments->getConfigurationOptions();
if ($cfg->getAllowedFileTypes())
$fileupload_config['extensions']->set('default', $cfg->getAllowedFileTypes());
foreach ($fileupload_config as $C) {
$C->set('visibility', new VisibilityConstraint(new Q(array(
'attachments__eq'=>true,
)), VisibilityConstraint::HIDDEN));
}
return array(
'attachments' => new BooleanField(array(
'label'=>__('Enable Attachments'),
'default'=>$cfg->allowAttachments(),
'configuration'=>array(
'desc'=>__('Enables attachments, regardless of channel'),
'validators' => function($self, $value) {
if (!ini_get('file_uploads'))
$self->addError(__('The "file_uploads" directive is disabled in php.ini'));
}
+ $fileupload_config;
function isAttachmentsEnabled() {
$config = $this->getConfiguration();
return $config['attachments'];
}
if ($hint = $this->getLocal('hint'))
$this->set('placeholder', $hint);
$this->set('hint', null);
$widget = parent::getWidget($widgetClass);
return $widget;
}
}
class PriorityField extends ChoiceField {
function getWidget($widgetClass=false) {
$widget = parent::getWidget($widgetClass);
if ($widget->value instanceof Priority)
$widget->value = $widget->value->getId();
return $widget;
}
function hasIdValue() {
return true;
}
function getChoices($verbose=false) {
$sql = 'SELECT priority_id, priority_desc FROM '.PRIORITY_TABLE
.' ORDER BY priority_urgency DESC';
$choices = array('' => '— '.__('Default').' —');
if (!($res = db_query($sql)))
return $choices;
while ($row = db_fetch_row($res))
$choices[$row[0]] = $row[1];
return $choices;
}
function parse($id) {
return $this->to_php(null, $id);
}
function to_php($value, $id=false) {
if ($value instanceof Priority)
return $value;
if (is_array($id)) {
reset($id);
$id = key($id);
}
elseif (is_array($value))
list($value, $id) = $value;
elseif ($id === false)
$id = $value;
if ($id)
return Priority::lookup($id);
}
function to_database($prio) {
return ($prio instanceof Priority)
? array($prio->getDesc(), $prio->getId())
: $prio;
}
function display($prio, &$styles=null) {
if (!$prio instanceof Priority)
return parent::display($prio);
if (is_array($styles))
$styles += array(
'background-color' => $prio->getColor()
);
return Format::htmlchars($prio->getDesc());
function toString($value) {
return ($value instanceof Priority) ? $value->getDesc() : $value;
}
function whatChanged($before, $after) {
return FormField::whatChanged($before, $after);
}
function searchable($value) {
// Priority isn't searchable this way
return null;
}
function getKeys($value) {
return ($value instanceof Priority) ? array($value->getId()) : null;
}
function getConfigurationOptions() {
$choices = $this->getChoices();
$choices[''] = __('System Default');
return array(
'prompt' => new TextboxField(array(
'id'=>2, 'label'=>__('Prompt'), 'required'=>false, 'default'=>'',
'hint'=>__('Leading text shown before a value is selected'),
'configuration'=>array('size'=>40, 'length'=>40),
)),
'default' => new ChoiceField(array(
'id'=>3, 'label'=>__('Default'), 'required'=>false, 'default'=>'',
'choices' => $choices,
'hint'=>__('Default selection for this field'),
'configuration'=>array('size'=>20, 'length'=>40),
)),
function getConfiguration() {
global $cfg;
$config = parent::getConfiguration();
if (!isset($config['default']))
$config['default'] = $cfg->getDefaultPriorityId();
return $config;
}
function applyOrderBy($query, $reverse=false, $name=false) {
if ($query->model == 'Ticket' && $name == 'cdata__priority') {
// Order by the priority urgency field
$col = 'cdata__:priority__priority_urgency';
$reverse = !$reverse;
}
else {
$col = $name ?: CustomQueue::getOrmPath($this->get('name'), $query);
}
if ($reverse)
$col = "-$col";
return $query->order_by($col);
}
FormField::addFieldTypes(/*@trans*/ 'Dynamic Fields', function() {
'priority' => array(__('Priority Level'), PriorityField),
class TimezoneField extends ChoiceField {
static $widget = 'TimezoneWidget';
function hasIdValue() {
return false;
}
function getChoices($verbose=false) {
global $cfg;
$choices = array();
foreach (DateTimeZone::listIdentifiers() as $zone)
$choices[$zone] = str_replace('/',' / ',$zone);
return $choices;
}
function whatChanged($before, $after) {
return FormField::whatChanged($before, $after);
}
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
function searchable($value) {
return null;
}
function getConfigurationOptions() {
return array(
'autodetect' => new BooleanField(array(
'id'=>1, 'label'=>__('Auto Detect'), 'required'=>false, 'default'=>true,
'configuration'=>array(
'desc'=>__('Add Auto Detect Button'))
)),
'prompt' => new TextboxField(array(
'id'=>2, 'label'=>__('Prompt'), 'required'=>false, 'default'=>'',
'hint'=>__('Leading text shown before a value is selected'),
'configuration'=>array('size'=>40, 'length'=>40),
)),
);
}
}
class DepartmentField extends ChoiceField {
function getWidget($widgetClass=false) {
$widget = parent::getWidget($widgetClass);
if ($widget->value instanceof Dept)
$widget->value = $widget->value->getId();
return $widget;
}
function hasIdValue() {
return true;
}
function getChoices($verbose=false) {
$selected = self::getWidget();
aydreeihn
committed
if($selected && $selected->value) {
if(is_array($selected->value)) {
foreach ($selected->value as $k => $v) {
$current_id = $k;
$current_name = $v;
}
}
else {
$current_id = $selected->value;
$current_name = Dept::getNameById($current_id);
$addNew = true;
}
}
$active_depts = array();
if($current_id)
$active_depts = Dept::objects()
->filter(array('flags__hasbit' => Dept::FLAG_ACTIVE))
->values('id', 'name');
aydreeihn
committed
if ($depts = Dept::getDepartments(null, true, Dept::DISPLAY_DISABLED)) {
//create array w/queryset
$active = array();
foreach ($active_depts as $dept)
$active[$dept['id']] = $dept['name'];
//add selected dept to list
$active[$current_id] = $current_name;
aydreeihn
committed
foreach ($depts as $id => $name) {
$choices[$id] = $name;
if(!array_key_exists($id, $active) && $current_id)
unset($choices[$id]);
}
}
if($addNew)
$choices[':new:'] = '— '.__('Add New').' —';
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
return $choices;
}
function parse($id) {
return $this->to_php(null, $id);
}
function to_php($value, $id=false) {
if (is_array($id)) {
reset($id);
$id = key($id);
}
return $id;
}
function to_database($dept) {
return ($dept instanceof Dept)
? array($dept->getName(), $dept->getId())
: $dept;
}
function toString($value) {
return (string) $value;
}
function searchable($value) {
return null;
}
function getConfigurationOptions() {
return array(
'prompt' => new TextboxField(array(
'id'=>2, 'label'=>__('Prompt'), 'required'=>false, 'default'=>'',
'hint'=>__('Leading text shown before a value is selected'),
'configuration'=>array('size'=>40, 'length'=>40),
)),
);
}
}
FormField::addFieldTypes(/*@trans*/ 'Dynamic Fields', function() {
return array(
'department' => array(__('Department'), DepartmentField),
);
});
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
class SLAField extends ChoiceField {
function getWidget($widgetClass=false) {
$widget = parent::getWidget($widgetClass);
if ($widget->value instanceof SLA)
$widget->value = $widget->value->getId();
return $widget;
}
function hasIdValue() {
return true;
}
function getChoices($verbose=false) {
global $cfg;
$choices = array();
if (($depts = SLA::getSLAs()))
foreach ($depts as $id => $name)
$choices[$id] = $name;
return $choices;
}
function parse($id) {
return $this->to_php(null, $id);
}
function to_php($value, $id=false) {
if (is_array($id)) {
reset($id);
$id = key($id);
}
return $id;
}
function to_database($sla) {
return ($sla instanceof SLA)
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
: $sla;
}
function toString($value) {
return (string) $value;
}
function searchable($value) {
return null;
}
function getConfigurationOptions() {
return array(
'prompt' => new TextboxField(array(
'id'=>2, 'label'=>__('Prompt'), 'required'=>false, 'default'=>'',
'hint'=>__('Leading text shown before a value is selected'),
'configuration'=>array('size'=>40, 'length'=>40),
)),
);
}
}
class AssigneeField extends ChoiceField {
function getWidget($widgetClass=false) {
$widget = parent::getWidget($widgetClass);
if (is_object($widget->value))
$widget->value = $widget->value->getId();
return $widget;
}
function getCriteria() {
if (!isset($this->_criteria)) {
$this->_criteria = array('available' => true);
if (($c=parent::getCriteria()))
$this->_criteria = array_merge($this->_criteria, $c);
}
return $this->_criteria;
}
function hasIdValue() {
return true;
}
function setChoices($choices) {
$this->_choices = $choices;
}
function getChoices($verbose=false) {
if (!isset($this->_choices)) {
$config = $this->getConfiguration();
$choices = array(
__('Agents') => new ArrayObject(),
__('Teams') => new ArrayObject());
$A = current($choices);
$criteria = $this->getCriteria();
$agents = array();
if (($dept=$config['dept']) && $dept->assignMembersOnly()) {
if (($members = $dept->getAvailableMembers()))
foreach ($members as $member)
$agents[$member->getId()] = $member;
} else {
$agents = Staff::getStaffMembers($criteria);
}
$A['s'.$id] = $name;
if (($teams = Team::getActiveTeams()))
foreach ($teams as $id => $name)
$T['t'.$id] = $name;
$this->_choices = $choices;
}
return $this->_choices;
function getValue() {
if (($value = parent::getValue()) && ($id=$this->getClean()))
return $value[$id];
}
function parse($id) {
return $this->to_php(null, $id);
}
function to_php($value, $id=false) {
if (is_array($id)) {
reset($id);
$id = key($id);
switch ($type) {
case 's':
return Staff::lookup($id);
case 't':
return Team::lookup($id);
case 'd':
return Dept::lookup($id);
default:
return $id;
}
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
}
function to_database($value) {
return (is_object($value))
? array($value->getName(), $value->getId())
: $value;
}
function toString($value) {
return (string) $value;
}
function searchable($value) {
return null;
}
function getConfigurationOptions() {
return array(
'prompt' => new TextboxField(array(
'id'=>2, 'label'=>__('Prompt'), 'required'=>false, 'default'=>'',
'hint'=>__('Leading text shown before a value is selected'),
'configuration'=>array('size'=>40, 'length'=>40),
)),
);
}
}
FormField::addFieldTypes(/*@trans*/ 'Dynamic Fields', function() {
return array(
'assignee' => array(__('Assignee'), AssigneeField),
);
});
class TicketStateField extends ChoiceField {
'name' => /* @trans, @context "ticket state name" */ 'Open',
'verb' => /* @trans, @context "ticket state action" */ 'Open'
'name' => /* @trans, @context "ticket state name" */ 'Closed',
'verb' => /* @trans, @context "ticket state action" */ 'Close'
// Private states
static $_privatestates = array(
'name' => /* @trans, @context "ticket state name" */ 'Archived',
'verb' => /* @trans, @context "ticket state action" */ 'Archive'
'name' => /* @trans, @context "ticket state name" */ 'Deleted',
'verb' => /* @trans, @context "ticket state action" */ 'Delete'
);
function hasIdValue() {
return true;
}
function isChangeable() {
return false;
}
function getChoices($verbose=false) {
$states = static::$_states;
if ($this->options['private_too'])
$states += static::$_privatestates;
if (!isset($_choices)) {
// Translate and cache the choices
foreach ($states as $k => $v)
$_choices[$k] = _P('ticket state name', $v['name']);
$this->ht['default'] = '';
}
return $_choices;
}
function getChoice($state) {
if ($state && is_array($state))
$state = key($state);
if (isset(static::$_states[$state]))
return _P('ticket state name', static::$_states[$state]['name']);
if (isset(static::$_privatestates[$state]))
return _P('ticket state name', static::$_privatestates[$state]['name']);
}
function getConfigurationOptions() {
return array(
'prompt' => new TextboxField(array(
'id'=>2, 'label'=> __('Prompt'), 'required'=>false, 'default'=>'',
'hint'=> __('Leading text shown before a value is selected'),
'configuration'=>array('size'=>40, 'length'=>40),
)),
);
}