diff --git a/include/ajax.forms.php b/include/ajax.forms.php index e61ddec81fd5eb0bed60c2a024272acd10ad5300..8dc11185cdfae713947d745e245c2764c27824db 100644 --- a/include/ajax.forms.php +++ b/include/ajax.forms.php @@ -50,6 +50,7 @@ class DynamicFormsAjaxAPI extends AjaxController { } function saveFieldConfiguration($field_id) { + if (!($field = DynamicFormField::lookup($field_id))) Http::response(404, 'No such field'); @@ -75,13 +76,12 @@ class DynamicFormsAjaxAPI extends AjaxController { function($a, $b) { return $a | $b; }, 0); $field->flags = $flags | $preserve; - if (!$field->setConfiguration()) { - include STAFFINC_DIR . 'templates/dynamic-field-config.tmpl.php'; - return; - } - else + if ($field->setConfiguration($_POST)) { $field->save(); - Http::response(201, 'Field successfully updated'); + Http::response(201, 'Field successfully updated'); + } + + include STAFFINC_DIR . 'templates/dynamic-field-config.tmpl.php'; } function deleteAnswer($entry_id, $field_id) { @@ -175,7 +175,7 @@ class DynamicFormsAjaxAPI extends AjaxController { $icon = ($list->get('sort_mode') == 'SortCol') ? '<i class="icon-sort"></i> ' : ''; - if (!$valid || !$item->setConfiguration()) { + if (!$valid || !$item->setConfiguration($_POST)) { include STAFFINC_DIR . 'templates/list-item-properties.tmpl.php'; return; } diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php index d9d51ef8871661ecd702edc2a53e6fac238a2323..d97e4b348683f47c6a1f6c9ac71668d303b9261c 100644 --- a/include/class.dynamic_forms.php +++ b/include/class.dynamic_forms.php @@ -562,6 +562,7 @@ class DynamicFormField extends VerySimpleModel { * configuration of this field * * Parameters: + * vars - POST request / data * errors - (OUT array) receives validation errors of the parsed * configuration form * @@ -570,15 +571,17 @@ class DynamicFormField extends VerySimpleModel { * errors. If false, the errors were written into the received errors * array. */ - function setConfiguration(&$errors=array()) { + function setConfiguration($vars, &$errors=array()) { $config = array(); - foreach ($this->getConfigurationForm($_POST)->getFields() as $name=>$field) { + foreach ($this->getConfigurationForm($vars)->getFields() as $name=>$field) { $config[$name] = $field->to_php($field->getClean()); $errors = array_merge($errors, $field->errors()); } if (count($errors) === 0) $this->set('configuration', JsonDataEncoder::encode($config)); - $this->set('hint', Format::sanitize($_POST['hint'])); + + $this->set('hint', Format::sanitize($vars['hint'])); + return count($errors) === 0; } @@ -1323,12 +1326,20 @@ class SelectionField extends FormField { $config = $this->getConfiguration(); $choices = $this->getChoices(); $selection = array(); + + if ($value && !is_array($value)) + $value = array($value); + if ($value && is_array($value)) { foreach ($value as $k=>$v) { - if (($i=$list->getItem((int) $k))) + if ($k && ($i=$list->getItem((int) $k))) $selection[$i->getId()] = $i->getValue(); elseif (isset($choices[$k])) $selection[$k] = $choices[$k]; + elseif (isset($choices[$v])) + $selection[$v] = $choices[$v]; + elseif (($i=$list->getItem($v, true))) + $selection[$i->getId()] = $i->getValue(); } } elseif($value) { //Assume invalid textbox input to be validated @@ -1656,6 +1667,11 @@ class TypeaheadSelectionWidget extends ChoicesWidget { $data = $this->field->getSource(); if (isset($data[$this->name])) return $data[$this->name]; + + $name = $this->field->get('name'); + if (isset($data[$name])) + return $data[$name]; + return parent::getValue(); } @@ -1665,7 +1681,10 @@ class TypeaheadSelectionWidget extends ChoicesWidget { if (isset($data[$this->name.'_name'])) { // Drop the extra part, if any $v = $data[$this->name.'_name']; - $v = substr($v, 0, strrpos($v, ' — ')); + $pos = strrpos($v, ' — '); + if ($pos !== false) + $v = substr($v, 0, $pos); + return trim($v); } return parent::getValue(); diff --git a/include/class.list.php b/include/class.list.php index a228ab06f2bf04c0eb31f12dc827d37e5d585eaf..12d2a85565a4062c4f8c24aca91ada5378bfd404 100644 --- a/include/class.list.php +++ b/include/class.list.php @@ -227,23 +227,27 @@ class DynamicList extends VerySimpleModel implements CustomList { return $this->_items; } - - - function getItem($val) { + 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)); else - $items->filter(Q::any(array('value'=>$val, '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( 'status' => 1, 'list_id' => $this->getId(), @@ -513,7 +517,7 @@ class DynamicList extends VerySimpleModel implements CustomList { } } - // 'name' and 'email' MUST be in the headers + // 'value' MUST be in the headers if (!isset($headers['value'])) return __('CSV file must include `value` column'); @@ -565,11 +569,11 @@ class DynamicList extends VerySimpleModel implements CustomList { $items[] = $data; } - $errors = array(); foreach ($items as $u) { $vars = array_combine($keys, $u); - $item = $this->addItem($vars); - if (!$item || !$item->setConfiguration($errors, $vars)) + $errors = array(); + $item = $this->addItem($vars, $errors); + if (!$item || !$item->setConfiguration($vars, $errors)) return sprintf(__('Unable to import item: %s'), print_r($vars, true)); } @@ -698,16 +702,19 @@ class DynamicListItem extends VerySimpleModel implements CustomListItem { return $this->_config; } - function setConfiguration(&$errors=array(), $source=false) { + function setConfiguration($vars, &$errors=array()) { $config = array(); - foreach ($this->getConfigurationForm($source ?: $_POST)->getFields() as $field) { + foreach ($this->getConfigurationForm($vars)->getFields() as $field) { $config[$field->get('id')] = $field->to_php($field->getClean()); $errors = array_merge($errors, $field->errors()); } - if (count($errors) === 0) - $this->set('properties', JsonDataEncoder::encode($config)); - return count($errors) === 0; + if ($errors) + return false; + + $this->set('properties', JsonDataEncoder::encode($config)); + + return $this->save(); } function getConfigurationForm($source=null) { @@ -1228,9 +1235,9 @@ class TicketStatus extends VerySimpleModel implements CustomListItem { return $this->_settings; } - function setConfiguration(&$errors=array()) { + function setConfiguration($vars, &$errors=array()) { $properties = array(); - foreach ($this->getConfigurationForm($_POST)->getFields() as $f) { + foreach ($this->getConfigurationForm($vars)->getFields() as $f) { if ($this->isInternal() //Item is internal. && !$f->isEditable()) continue; diff --git a/setup/cli/modules/list.php b/setup/cli/modules/list.php new file mode 100644 index 0000000000000000000000000000000000000000..33867acba77236c8cb61a6f1752cfcb310f6f4b3 --- /dev/null +++ b/setup/cli/modules/list.php @@ -0,0 +1,89 @@ +<?php +require_once dirname(__file__) . "/class.module.php"; +require_once dirname(__file__) . "/../cli.inc.php"; +include_once INCLUDE_DIR .'class.translation.php'; + + +class ListManager extends Module { + var $prologue = 'CLI list manager'; + var $arguments = array( + 'action' => array( + 'help' => 'Action to be performed', + 'options' => array( + 'import' => 'Import list items to the system', + 'export' => 'Export list items from the system', + 'show' => 'Show the lists', + ), + ), + ); + + + var $options = array( + 'file' => array('-f', '--file', 'metavar'=>'path', + 'help' => 'File or stream to process'), + 'id' => array('-ID', '--id', 'metavar'=>'id', + 'help' => 'List ID'), + ); + + var $stream; + + function run($args, $options) { + + Bootstrap::connect(); + + $list = null; + if ($options['id']) + $list = DynamicList::lookup($options['id']); + + switch ($args['action']) { + case 'import': + if (!$list) + $this->fail("List ID required for items import"); + + // Properly detect Macintosh style line endings + ini_set('auto_detect_line_endings', true); + if (!$options['file']) + $this->fail('CSV file to import list items from is required!'); + elseif (!($this->stream = fopen($options['file'], 'rb'))) + $this->fail("Unable to open input file [{$options['file']}]"); + + $extras = array(); + $status = $list->importCsv($this->stream, $extras); + if (is_numeric($status)) + $this->stderr->write("Successfully imported $status list items\n"); + else + $this->fail($status); + break; + case 'export': + + if (!$list) + $this->fail("List ID required for export"); + + $stream = $options['file'] ?: 'php://stdout'; + if (!($this->stream = fopen($stream, 'c'))) + $this->fail("Unable to open output file [{$options['file']}]"); + + fputcsv($this->stream, array('Value', 'Abbrev')); + foreach ($list->getItems() as $item) + fputcsv($this->stream, array( + (string) $item->getValue(), + $item->getAbbrev())); + break; + case 'show': + $lists = DynamicList::objects()->order_by('-type', 'name'); + foreach ($lists as $list) { + $this->stdout->write(sprintf("%d %s \n", + $list->getId(), + $list->getName(), + $list->getPluralName() ?: $list->getName() + )); + } + break; + default: + $this->stderr->write('Unknown action!'); + } + @fclose($this->stream); + } +} +Module::register('list', 'ListManager'); +?>