Skip to content
Snippets Groups Projects
class.list.php 40.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • <?php
    /*********************************************************************
        class.list.php
    
        Custom List utils
    
        Jared Hancock <jared@osticket.com>
        Peter Rotich <peter@osticket.com>
        Copyright (c)  2014 osTicket
        http://www.osticket.com
    
        Released under the GNU General Public License WITHOUT ANY WARRANTY.
        See LICENSE.TXT for details.
    
        vim: expandtab sw=4 ts=4 sts=4:
    **********************************************************************/
    require_once(INCLUDE_DIR .'class.dynamic_forms.php');
    
    require_once(INCLUDE_DIR .'class.variable.php');
    
    
    /**
     * Interface for Custom Lists
     *
     * Custom lists are used to represent list of arbitrary data that can be
     * used as dropdown or typeahead selections in dynamic forms. This model
     * defines a list. The individual items are stored in the "Item" model.
     *
     */
    
    interface CustomList {
    
        function getId();
        function getName();
        function getPluralName();
    
        function getNumItems();
        function getAllItems();
        function getItems($criteria);
    
    
        function getItem($id);
        function addItem($vars, &$errors);
    
        function isItemUnique($vars);
    
        function getForm(); // Config form
        function hasProperties();
    
        function getConfigurationForm();
        function getSummaryFields();
    
    
        function getSortModes();
    
        function getSortMode();
    
        function getListOrderBy();
    
    
        function allowAdd();
        function hasAbbrev();
    
    
        function update($vars, &$errors);
        function delete();
    
        static function create($vars, &$errors);
    
        static function lookup($id);
    }
    
    /*
     * Custom list item interface
     */
    interface CustomListItem {
        function getId();
        function getValue();
        function getAbbrev();
        function getSortOrder();
    
    
    Peter Rotich's avatar
    Peter Rotich committed
        function getList();
        function getListId();
    
    
        function getConfiguration();
    
    
    Peter Rotich's avatar
    Peter Rotich committed
        function hasProperties();
    
        function isEnabled();
        function isDeletable();
        function isEnableable();
        function isInternal();
    
        function enable();
        function disable();
    
        function update($vars, &$errors);
        function delete();
    
     * Base class for Custom List handlers
    
     * Custom list handler extends custom list and might store data outside the
     * typical dynamic list store.
    
        function __construct($list) {
            $this->_list = $list;
    
            $rv = null;
            if ($this->_list && is_callable(array($this->_list, $name)))
                $rv = $args
                    ? call_user_func_array(array($this->_list, $name), $args)
                    : call_user_func(array($this->_list, $name));
    
        function __get($field) {
            return $this->_list->{$field};
        }
    
    
        function update($vars, &$errors) {
            return $this->_list->update($vars, $errors);
    
        abstract function getListOrderBy();
    
        abstract function getNumItems();
        abstract function getAllItems();
        abstract function getItems($criteria);
        abstract function getItem($id);
        abstract function addItem($vars, &$errors);
    
    
        static protected $registry = array();
        static function forList(/* CustomList */ $list) {
            if ($list->type && ($handler = static::$registry[$list->type]))
                return new $handler($list);
            return $list;
        }
        static function register($type, $handler) {
            static::$registry[$type] = $handler;
        }
    
    }
    
    /**
     * Dynamic lists are Custom Lists solely defined by the user.
     *
     */
    class DynamicList extends VerySimpleModel implements CustomList {
    
        static $meta = array(
            'table' => LIST_TABLE,
            'ordering' => array('name'),
            'pk' => array('id'),
    
            'joins' => array(
                'items' => array(
                    'reverse' => 'DynamicListItem.list',
                ),
            ),
    
        );
    
        // Required fields
        static $fields = array('name', 'name_plural', 'sort_mode', 'notes');
    
    
        // Supported masks
        const MASK_EDIT     = 0x0001;
        const MASK_ADD      = 0x0002;
        const MASK_DELETE   = 0x0004;
        const MASK_ABBREV   = 0x0008;
    
    
        var $_items;
        var $_form;
    
    
        function getId() {
            return $this->get('id');
    
        }
    
        function getInfo() {
            return $this->ht;
        }
    
        function hasProperties() {
            return ($this->getForm() && $this->getForm()->getFields());
        }
    
        function getSortModes() {
    
            return array(
                'Alpha'     => __('Alphabetical'),
                '-Alpha'    => __('Alphabetical (Reversed)'),
                'SortCol'   => __('Manually Sorted')
            );
    
        function getSortMode() {
            return $this->sort_mode;
        }
    
    
        function getListOrderBy() {
    
            switch ($this->getSortMode()) {
    
                case 'Alpha':   return 'value';
                case '-Alpha':  return '-value';
                case 'SortCol': return 'sort';
            }
        }
    
        function getName() {
    
            return $this->getLocal('name');
    
        }
    
        function getPluralName() {
    
            if ($name = $this->getLocal('name_plural'))
    
                return $name;
            else
    
                return $this->getName() . 's';
    
        }
    
        function getItemCount() {
            return DynamicListItem::objects()->filter(array('list_id'=>$this->id))
                ->count();
        }
    
        function getNumItems() {
            return $this->getItemCount();
        }
    
        function getAllItems() {
             return DynamicListItem::objects()->filter(
                    array('list_id'=>$this->get('id')))
                    ->order_by($this->getListOrderBy());
        }
    
    
        function search($q) {
            $items = clone $this->getAllItems();
            return $items->filter(Q::any(array(
                'value__startswith' => $q,
                'extra__contains' => $q,
                'properties__contains' => '"'.$q,
            )));
        }
    
    
        function getItems($limit=false, $offset=false) {
            if (!$this->_items) {
                $this->_items = DynamicListItem::objects()->filter(
                    array('list_id'=>$this->get('id'),
                          'status__hasbit'=>DynamicListItem::ENABLED))
                    ->order_by($this->getListOrderBy());
                if ($limit)
                    $this->_items->limit($limit);
                if ($offset)
                    $this->_items->offset($offset);
            }
            return $this->_items;
        }
    
    
        function getItem($val, $extra=false) {
    
            $items = DynamicListItem::objects()->filter(
                    array('list_id' => $this->getId()));
    
    
            if (is_int($val))
    
                $items->filter(array('id' => $val));
    
            elseif ($extra)
                $items->filter(array('extra' => $val));
    
                $items->filter(array('value' => $val));
    
    
            return $items->first();
    
        }
    
        function addItem($vars, &$errors) {
    
            if (($item=$this->getItem($vars['value'])))
                return $item;
    
    
            $item = DynamicListItem::create(array(
    
    Peter Rotich's avatar
    Peter Rotich committed
                'status' => 1,
    
                'list_id' => $this->getId(),
                'sort'  => $vars['sort'],
                'value' => $vars['value'],
    
                'extra' => $vars['extra']
    
            ));
            $this->_items = false;
    
            return $item;
        }
    
    
        function isItemUnique($data) {
            try {
                $this->getItems()->filter(array('value'=>$data['value']))->one();
                return false;
            }
            catch (DoesNotExist $e) {
                return true;
            }
        }
    
    
        function getConfigurationForm($autocreate=false) {
    
            if (!$this->_form) {
    
                $this->_form = DynamicForm::lookup(array('type'=>'L'.$this->getId()));
                if (!$this->_form
                        && $autocreate
                        && $this->createConfigurationForm())
                    return $this->getConfigurationForm(false);
    
            return $this->_form;
        }
    
    
        function getListItemBasicForm($source=null, $item=false) {
            return new SimpleForm(array(
                'value' => 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);
        }
    
        // Fields shown on the list items page
        function getSummaryFields() {
    
            $prop_fields = array();
    
            foreach ($this->getConfigurationForm()->getFields() as $f) {
                if (in_array($f->get('type'), array('text', 'datetime', 'phone')))
                    $prop_fields[] = $f;
                if (strpos($f->get('type'), 'list-') === 0)
                    $prop_fields[] = $f;
    
                // 4 property columns max
                if (count($prop_fields) == 4)
                    break;
            }
            return $prop_fields;
        }
    
    
        function isDeleteable() {
            return !$this->hasMask(static::MASK_DELETE);
        }
    
        function isEditable() {
            return !$this->hasMask(static::MASK_EDIT);
        }
    
        function allowAdd() {
            return !$this->hasMask(static::MASK_ADD);
        }
    
        function hasAbbrev() {
            return !$this->hasMask(static::MASK_ABBREV);
        }
    
        protected function hasMask($mask) {
            return 0 !== ($this->get('masks') & $mask);
        }
    
        protected function clearMask($mask) {
            return $this->set('masks', $this->get('masks') & ~$mask);
        }
    
        protected function setFlag($mask) {
            return $this->set('mask', $this->get('mask') | $mask);
        }
    
    
        private function createConfigurationForm() {
    
            $form = DynamicForm::create(array(
                        'type' => 'L'.$this->getId(),
                        'title' => $this->getName() . ' Properties'
            ));
    
            return $form->save(true);
        }
    
        function getForm($autocreate=true) {
            return $this->getConfigurationForm($autocreate);
    
            return JsonDataParser::parse($this->configuration);
    
        function getTranslateTag($subtag) {
            return _H(sprintf('list.%s.%s', $subtag, $this->id));
        }
        function getLocal($subtag) {
            $tag = $this->getTranslateTag($subtag);
            $T = CustomDataTranslation::translate($tag);
            return $T != $tag ? $T : $this->get($subtag);
        }
    
    
        function update($vars, &$errors) {
    
    
            $required = array();
            if ($this->isEditable())
                $required = array('name');
    
    
            foreach (static::$fields as $f) {
                if (in_array($f, $required) && !$vars[$f])
    
                    $errors[$f] = sprintf(__('%s is required'), mb_convert_case($f, MB_CASE_TITLE));
    
                elseif (isset($vars[$f]))
                    $this->set($f, $vars[$f]);
            }
    
            if ($errors)
                return false;
    
            return $this->save(true);
        }
    
        function save($refetch=false) {
            if (count($this->dirty))
                $this->set('updated', new SqlFunction('NOW'));
            if (isset($this->dirty['notes']))
                $this->notes = Format::sanitize($this->notes);
    
            return parent::save($refetch);
        }
    
        function delete() {
            $fields = DynamicFormField::objects()->filter(array(
                'type'=>'list-'.$this->id))->count();
    
    
            // Refuse to delete lists that are in use by fields
            if ($fields != 0)
                return false;
    
            if (!parent::delete())
    
                return false;
    
    
            if (($form = $this->getForm(false))) {
                $form->delete(false);
                $form->fields->delete();
            }
    
            return true;
    
        private function createForm() {
    
            $form = DynamicForm::create(array(
                        'type' => 'L'.$this->getId(),
                        'title' => $this->getName() . ' Properties'
            ));
    
            return $form->save(true);
        }
    
        static function add($vars, &$errors) {
    
            $required = array('name');
            $ht = array();
            foreach (static::$fields as $f) {
                if (in_array($f, $required) && !$vars[$f])
    
                    $errors[$f] = sprintf(__('%s is required'), mb_convert_case($f, MB_CASE_TITLE));
    
                elseif(isset($vars[$f]))
                    $ht[$f] = $vars[$f];
            }
    
            if (!$ht || $errors)
                return false;
    
            // Create the list && form
            if (!($list = self::create($ht))
                    || !$list->save(true)
                    || !$list->createConfigurationForm())
                return false;
    
            return $list;
        }
    
    
        static function create($ht=false, &$errors=array()) {
    
            if (isset($ht['configuration'])) {
                $ht['configuration'] = JsonDataEncoder::encode($ht['configuration']);
            }
    
    
            $inst = new static($ht);
    
            $inst->set('created', new SqlFunction('NOW'));
    
    
            if (isset($ht['properties'])) {
                $inst->save();
                $ht['properties']['type'] = 'L'.$inst->getId();
                $form = DynamicForm::create($ht['properties']);
                $form->save();
            }
    
            if (isset($ht['items'])) {
                $inst->save();
                foreach ($ht['items'] as $i) {
                    $i['list_id'] = $inst->getId();
                    $item = DynamicListItem::create($i);
                    $item->save();
                }
            }
    
    
        static function lookup($id) {
    
            if (!($list = parent::lookup($id)))
                return null;
    
            if (($config = $list->getConfiguration())) {
                if (($lh=$config['handler']) && class_exists($lh))
                    $list = new $lh($list);
            }
    
            return $list;
        }
    
    
        static function getSelections() {
            $selections = array();
            foreach (DynamicList::objects() as $list) {
                $selections['list-'.$list->id] =
                    array($list->getPluralName(),
                        SelectionField, $list->get('id'));
            }
            return $selections;
        }
    
    
    Peter Rotich's avatar
    Peter Rotich committed
       function importCsv($stream, $defaults=array()) {
            require_once INCLUDE_DIR . 'class.import.php';
    
    
            $form = $this->getConfigurationForm();
    
    Peter Rotich's avatar
    Peter Rotich committed
            $fields = array(
    
                'value' => new TextboxField(array(
                    'label' => __('Value'),
                    'name' => 'value',
                    'configuration' => array(
                        'length' => 0,
                    ),
                )),
                'abbrev' => new TextboxField(array(
    
    Peter Rotich's avatar
    Peter Rotich committed
                    'name' => 'extra',
    
                    'label' => __('Abbreviation'),
                    'configuration' => array(
                        'length' => 0,
                    ),
                )),
            );
    
    
    Peter Rotich's avatar
    Peter Rotich committed
            $form = $this->getConfigurationForm();
            if ($form && ($custom_fields = $form->getFields())
                    && count($custom_fields)) {
                foreach ($custom_fields as $f)
                    if ($f->get('name'))
                        $fields[$f->get('name')] = $f;
    
    Peter Rotich's avatar
    Peter Rotich committed
            $importer = new CsvImporter($stream);
            $imported = 0;
            try {
                db_autocommit(false);
                $records = $importer->importCsv($fields, $defaults);
                foreach ($records as $data) {
                    $errors = array();
                    $item = $this->addItem($data, $errors);
                    if ($item && $item->setConfiguration($data, $errors))
                        $imported++;
                    else
                        echo sprintf(__('Unable to import item: %s'), print_r($data, true));
    
    Peter Rotich's avatar
    Peter Rotich committed
                db_autocommit(true);
    
    Peter Rotich's avatar
    Peter Rotich committed
            catch (Exception $ex) {
                db_rollback();
                return $ex->getMessage();
    
    Peter Rotich's avatar
    Peter Rotich committed
            return $imported;
    
        }
    
        function importFromPost($stuff, $extra=array()) {
            if (is_array($stuff) && !$stuff['error']) {
                // Properly detect Macintosh style line endings
                ini_set('auto_detect_line_endings', true);
                $stream = fopen($stuff['tmp_name'], 'r');
            }
            elseif ($stuff) {
                $stream = fopen('php://temp', 'w+');
                fwrite($stream, $stuff);
                rewind($stream);
            }
            else {
                return __('Unable to parse submitted items');
            }
    
            return self::importCsv($stream, $extra);
        }
    
    FormField::addFieldTypes(/* @trans */ 'Custom Lists', array('DynamicList', 'getSelections'));
    
    
    /**
     * Represents a single item in a dynamic list
     *
     * Fields:
     * value - (char * 255) Actual list item content
     * extra - (char * 255) Other values that represent the same item in the
     *      list, such as an abbreviation. In practice, should be a
     *      space-separated list of tokens which should hit this list item in a
     *      search
     * sort - (int) If sorting by this field, represents the numeric sort order
     *      that this item should come in the dropdown list
     */
    
    class DynamicListItem extends VerySimpleModel implements CustomListItem {
    
    
        static $meta = array(
            'table' => LIST_ITEM_TABLE,
            'pk' => array('id'),
            'joins' => array(
                'list' => array(
                    'null' => true,
                    'constraint' => array('list_id' => 'DynamicList.id'),
                ),
            ),
        );
    
        var $_config;
        var $_form;
    
    
        const ENABLED   = 0x0001;
        const INTERNAL  = 0x0002;
    
    
        protected function hasStatus($flag) {
            return 0 !== ($this->get('status') & $flag);
        }
    
        protected function clearStatus($flag) {
            return $this->set('status', $this->get('status') & ~$flag);
        }
    
        protected function setStatus($flag) {
            return $this->set('status', $this->get('status') | $flag);
        }
    
    
        function isInternal() {
    
            return  $this->hasStatus(self::INTERNAL);
    
        }
    
        function isEnableable() {
            return true;
        }
    
    
    Peter Rotich's avatar
    Peter Rotich committed
        function isDisableable() {
            return !$this->isInternal();
        }
    
    
        function isDeletable() {
            return !$this->isInternal();
        }
    
    
        function isEnabled() {
            return $this->hasStatus(self::ENABLED);
        }
    
        function enable() {
            $this->setStatus(self::ENABLED);
        }
        function disable() {
            $this->clearStatus(self::ENABLED);
        }
    
    
    Peter Rotich's avatar
    Peter Rotich committed
        function hasProperties() {
            return ($this->getForm() && $this->getForm()->getFields());
        }
    
    
        function getId() {
            return $this->get('id');
        }
    
    
    Peter Rotich's avatar
    Peter Rotich committed
        function getList() {
            return $this->list;
        }
    
    
        function getListId() {
            return $this->get('list_id');
        }
    
    
        function getValue() {
    
            return $this->getLocal('value');
    
        }
    
        function getAbbrev() {
            return $this->get('extra');
        }
    
        function getSortOrder() {
            return $this->get('sort');
        }
    
        function getConfiguration() {
            if (!$this->_config) {
                $this->_config = $this->get('properties');
                if (is_string($this->_config))
                    $this->_config = JsonDataParser::parse($this->_config);
                elseif (!$this->_config)
                    $this->_config = array();
            }
            return $this->_config;
        }
    
    
        function setConfiguration($vars, &$errors=array()) {
    
            $config = array();
    
            foreach ($this->getConfigurationForm($vars)->getFields() as $field) {
    
                $config[$field->get('id')] = $field->to_php($field->getClean());
    
                $errors = array_merge($errors, $field->errors());
            }
    
    
            if ($errors)
                return false;
    
            $this->set('properties', JsonDataEncoder::encode($config));
    
            return $this->save();
    
        function getConfigurationForm($source=null) {
    
            if (!$this->_form) {
    
                $config = $this->getConfiguration();
    
                $this->_form = $this->list->getForm()->getForm($source);
    
                if (!$source && $config) {
    
                    $fields = $this->_form->getFields();
                    foreach ($fields as $f) {
    
                        $name = $f->get('id');
                        if (isset($config[$name]))
                            $f->value = $f->to_php($config[$name]);
                        else if ($f->get('default'))
                            $f->value = $f->get('default');
                    }
                }
    
            return $this->_form;
        }
    
    
        function getForm() {
            return $this->getConfigurationForm();
        }
    
    
    Peter Rotich's avatar
    Peter Rotich committed
        function getFields() {
            return $this->getForm()->getFields();
        }
    
    
        function getVar($name) {
            $config = $this->getConfiguration();
            $name = mb_strtolower($name);
            foreach ($this->getConfigurationForm()->getFields() as $field) {
                if (mb_strtolower($field->get('name')) == $name)
    
                    return $field->asVar($config[$field->get('id')]);
    
        function getFilterData() {
            $data = array();
            foreach ($this->getConfigurationForm()->getFields() as $F) {
                $data['.'.$F->get('id')] = $F->toString($F->value);
            }
    
            $data['.abb'] = (string) $this->get('extra');
    
        function getTranslateTag($subtag) {
            return _H(sprintf('listitem.%s.%s', $subtag, $this->id));
        }
        function getLocal($subtag) {
            $tag = $this->getTranslateTag($subtag);
            $T = CustomDataTranslation::translate($tag);
            return $T != $tag ? $T : $this->get($subtag);
        }
    
    
        function toString() {
            return $this->get('value');
        }
    
        function __toString() {
            return $this->toString();
        }
    
    
    Peter Rotich's avatar
    Peter Rotich committed
        function display() {
            return sprintf('<a class="preview" href="#"
                    data-preview="#list/%d/items/%d/preview">%s</a>',
                    $this->getListId(),
                    $this->getId(),
                    $this->getValue()
                    );
        }
    
    
        function update($vars, &$errors=array()) {
    
            if (!$vars['value']) {
    
                $errors['value-'.$this->getId()] = __('Value required');
    
                return false;
            }
    
    
            foreach (array(
                        'sort' => 'sort',
                        'value' => 'value',
                        'abbrev' => 'extra') as $k => $v) {
                if (isset($vars[$k]))
                    $this->set($v, $vars[$k]);
            }
    
    
            return $this->save();
    
        }
    
        function delete() {
            # Don't really delete, just unset the list_id to un-associate it with
            # the list
            $this->set('list_id', null);
            return $this->save();
        }
    
    
        static function create($ht=false, &$errors=array()) {
    
            if (isset($ht['properties']) && is_array($ht['properties']))
                $ht['properties'] = JsonDataEncoder::encode($ht['properties']);
    
    
            $inst = new static($ht);
    
    
            // Auto-config properties if any
            if ($ht['configuration'] && is_array($ht['configuration'])) {
                $config = $inst->getConfiguration();
                if (($form = $inst->getConfigurationForm())) {
                    foreach ($form->getFields() as $f) {
                        if (!isset($ht['configuration'][$f->get('name')]))
                            continue;
    
    
                        $config[$f->get('id')] =
                            $ht['configuration'][$f->get('name')];
    
                    }
                }
    
                $inst->set('properties', JsonDataEncoder::encode($config));
            }
    
            return $inst;
        }
    
    Peter Rotich's avatar
    Peter Rotich committed
    
    /*
     * Ticket status List
     *
     */
    
    
    class TicketStatusList extends CustomListHandler {
    
    Peter Rotich's avatar
    Peter Rotich committed
        // Fields of interest we need to store
        static $config_fields = array('sort_mode', 'notes');
    
    
        var $_items;
        var $_form;
    
    
        function getListOrderBy() {
            switch ($this->getSortMode()) {
                case 'Alpha':   return 'name';
                case '-Alpha':  return '-name';
                case 'SortCol': return 'sort';
            }
        }
    
    
    Peter Rotich's avatar
    Peter Rotich committed
        function getNumItems() {
    
    Peter Rotich's avatar
    Peter Rotich committed
            return TicketStatus::objects()->count();
    
        function getAllItems() {
            if (!$this->_items)
                $this->_items = TicketStatus::objects()->order_by($this->getListOrderBy());
    
    Peter Rotich's avatar
    Peter Rotich committed
    
    
            return $this->_items;
    
        function search($q) {
            $items = clone $this->getAllItems();
            return $items->filter(Q::any(array(
                'name__startswith' => $q,
                'properties__contains' => '"'.$q,
            )));
        }
    
    
        function getItems($criteria = array()) {
    
            // Default to only enabled items
            if (!isset($criteria['enabled']))
                $criteria['enabled'] = true;
    
            $filters =  array();
            if ($criteria['enabled'])
                $filters['mode__hasbit'] = TicketStatus::ENABLED;
            if ($criteria['states'] && is_array($criteria['states']))
                $filters['state__in'] = $criteria['states'];
    
            else
                $filters['state__isnull'] = false;
    
    
            $items = TicketStatus::objects();
            if ($filters)
                $items->filter($filters);
            if ($criteria['limit'])
                $items->limit($criteria['limit']);
            if ($criteria['offset'])
                $items->offset($criteria['offset']);
    
            $items->order_by($this->getListOrderBy());
    
            return $items;
    
        function getItem($val) {
    
            if (!is_int($val))
                $val = array('name' => $val);
    
    
             return TicketStatus::lookup($val, $this);
    
    Peter Rotich's avatar
    Peter Rotich committed
        }
    
        function addItem($vars, &$errors) {
            $item = TicketStatus::create(array(
    
    Peter Rotich's avatar
    Peter Rotich committed
                'sort'  => $vars['sort'],
    
                'name' => $vars['name'],
    
    Peter Rotich's avatar
    Peter Rotich committed
            ));
            $this->_items = false;
    
            return $item;
        }
    
    
        function isItemUnique($data) {
            try {
                $this->getItems()->filter(array('name'=>$data['name']))->one();
                return false;
            }
            catch (DoesNotExist $e) {
                return true;
            }
        }
    
    
    
        static function getStatuses($criteria=array()) {
    
    Peter Rotich's avatar
    Peter Rotich committed
    
            $statuses = array();
            if (($list = DynamicList::lookup(
                            array('type' => 'ticket-status'))))
    
                $statuses = $list->getItems($criteria);
    
    Peter Rotich's avatar
    Peter Rotich committed
    
            return $statuses;
        }
    
    
    Peter Rotich's avatar
    Peter Rotich committed
        static function __load() {
            require_once(INCLUDE_DIR.'class.i18n.php');
    
            $i18n = new Internationalization();
    
    Peter Rotich's avatar
    Peter Rotich committed
            $tpl = $i18n->getTemplate('list.yaml');
    
    Peter Rotich's avatar
    Peter Rotich committed
            foreach ($tpl->getData() as $f) {
    
    Peter Rotich's avatar
    Peter Rotich committed
                if ($f['type'] == 'ticket-status') {
                    $list = DynamicList::create($f);
                    $list->save();
    
    Peter Rotich's avatar
    Peter Rotich committed
            if (!$list || !($o=DynamicForm::objects()->filter(
                            array('type'=>'L'.$list->getId()))))
    
    Peter Rotich's avatar
    Peter Rotich committed
                return false;
    
            // Create default statuses
            if (($statuses = $i18n->getTemplate('ticket_status.yaml')->getData()))
                foreach ($statuses as $status)
                    TicketStatus::__create($status);
    
            return $o[0];
        }
    
    
        function getExtraConfigOptions($source=null) {
            $status_choices = array( 0 => __('System Default'));
            if (($statuses=TicketStatusList::getStatuses(
                            array( 'enabled' => true, 'states' =>
                                array('open')))))
                foreach ($statuses as $s)
                    $status_choices[$s->getId()] = $s->getName();
    
            return array(
                'allowreopen' => new BooleanField(array(
                    'label' =>__('Allow Reopen'),
    
    Peter Rotich's avatar
    Peter Rotich committed
                    'editable' => true,
    
                    'default' => isset($source['allowreopen'])
                        ?  $source['allowreopen']: true,
                    'id' => 'allowreopen',
                    'name' => 'allowreopen',
                    'configuration' => array(
                        'desc'=>__('Allow tickets on this status to be reopened by end users'),
                    ),