diff --git a/include/ajax.forms.php b/include/ajax.forms.php index 9a026e83c5861f5621678dcf0864f008efd44e3a..57959fe727d8b3ff90f06580f7e142497d5a9a8b 100644 --- a/include/ajax.forms.php +++ b/include/ajax.forms.php @@ -58,15 +58,27 @@ class DynamicFormsAjaxAPI extends AjaxController { $ent->delete(); } - function getListItemProperties($item_id) { - if (!($item = DynamicListItem::lookup($item_id))) + function getListItemProperties($list_id, $item_id) { + + if (is_numeric($list_id)) + $list = DynamicList::lookup($list_id); + else + $list = BuiltInCustomList::lookup($list_id); + + if (!($item = $list->getItem($item_id))) Http::response(404, 'No such list item'); include(STAFFINC_DIR . 'templates/list-item-properties.tmpl.php'); } - function saveListItemProperties($item_id) { - if (!($item = DynamicListItem::lookup($item_id))) + function saveListItemProperties($list_id, $item_id) { + + if (is_numeric($list_id)) + $list = DynamicList::lookup($list_id); + else + $list = BuiltInCustomList::lookup($list_id); + + if (!($item = $list->getItem($item_id))) Http::response(404, 'No such list item'); if (!$item->setConfiguration()) diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php index 9fa8253a949a7c58f89b63dc4a24851de1e52b5b..9c49000d050e4e211bf65e84d5b5acb594a30ea0 100644 --- a/include/class.dynamic_forms.php +++ b/include/class.dynamic_forms.php @@ -448,6 +448,14 @@ class DynamicFormField extends VerySimpleModel { return $this->get('edit_mask') & 8; } + function isChangeable() { + return ($this->get('edit_mask') & 16) == 0; + } + + function isConfigurable() { + return ($this->get('edit_mask') & 32) == 0; + } + /** * Used when updating the form via the admin panel. This represents * validation on the form field template, not data entered into a form diff --git a/include/class.list.php b/include/class.list.php index e2d7592af596a0285ed3ef60f0a0a8ca44061a76..2ba87622560907893962a6e62656310df4c21860 100644 --- a/include/class.list.php +++ b/include/class.list.php @@ -36,10 +36,14 @@ interface CustomList { function getAllItems(); function getItems($criteria); + function getItem($id); + function addItem($vars, &$errors); + function getForm(); // Config form function hasProperties(); function getSortModes(); + function getSortMode(); function getListOrderBy(); function isBuiltIn(); @@ -48,8 +52,35 @@ interface CustomList { 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(); + + function getConfiguration(); + function getConfigurationForm(); + + + function isEnabled(); + function isDeletable(); + function isEnableable(); + function isInternal(); + + function enable(); + function disable(); + + function update($vars, &$errors); + function delete(); } + /* * Base class for Built-in Custom Lists * @@ -81,11 +112,15 @@ abstract class BuiltInCustomList implements CustomList { abstract function getAllItems(); abstract function getItems($criteria); + abstract function addItem($vars, &$errors); + abstract function getForm(); // Config form abstract function hasProperties(); abstract function getListOrderBy(); + abstract function getSortMode(); + function getSortModes() { return static::$sort_modes; } @@ -186,8 +221,12 @@ class DynamicList extends VerySimpleModel implements CustomList { return static::$sort_modes; } + function getSortMode() { + return $this->sort_mode; + } + function getListOrderBy() { - switch ($this->sort_mode) { + switch ($this->getSortMode()) { case 'Alpha': return 'value'; case '-Alpha': return '-value'; case 'SortCol': return 'sort'; @@ -234,7 +273,15 @@ class DynamicList extends VerySimpleModel implements CustomList { return $this->_items; } - function addItem($vars) { + + + function getItem($id) { + return DynamicListItem::lookup(array( + 'id' => $id, + 'list_id' => $this->getId())); + } + + function addItem($vars, &$errors) { $item = DynamicListItem::create(array( 'list_id' => $this->getId(), @@ -250,16 +297,30 @@ class DynamicList extends VerySimpleModel implements CustomList { return $item; } - function getConfigurationForm() { + function getConfigurationForm($autocreate=false) { if (!$this->_form) { - $this->_form = DynamicForm::lookup( - array('type'=>'L'.$this->get('id'))); + $this->_form = DynamicForm::lookup(array('type'=>'L'.$this->getId())); + if (!$this->_form + && $autocreate + && $this->createConfigurationForm()) + return $this->getConfigurationForm(false); } + return $this->_form; } - function getForm() { - return $this->getConfigurationForm(); + 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); } function update($vars, &$errors) { @@ -295,6 +356,39 @@ class DynamicList extends VerySimpleModel implements CustomList { return false; } + 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()) { $inst = parent::create($ht); $inst->set('created', new SqlFunction('NOW')); @@ -326,7 +420,7 @@ FormField::addFieldTypes('Custom Lists', array('DynamicList', 'getSelections')); * 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 { +class DynamicListItem extends VerySimpleModel implements CustomListItem { static $meta = array( 'table' => LIST_ITEM_TABLE, @@ -356,6 +450,18 @@ class DynamicListItem extends VerySimpleModel { return $this->set('status', $this->get('status') | $flag); } + function isInternal() { + return false; + } + + function isEnableable() { + return true; + } + + function isDeletable() { + return !$this->isInternal(); + } + function isEnabled() { return $this->hasStatus(self::ENABLED); } @@ -371,6 +477,10 @@ class DynamicListItem extends VerySimpleModel { return $this->get('id'); } + function getListId() { + return $this->get('list_id'); + } + function getValue() { return $this->get('value'); } @@ -415,6 +525,10 @@ class DynamicListItem extends VerySimpleModel { return $this->_form; } + function getForm() { + return $this->getConfigurationForm(); + } + function getVar($name) { $config = $this->getConfiguration(); $name = mb_strtolower($name); @@ -432,7 +546,12 @@ class DynamicListItem extends VerySimpleModel { return $this->toString(); } - function update($vars, $save = true) { + function update($vars, &$errors=array()) { + + if (!$vars['value']) { + $errors['value-'.$this->getId()] = 'Value required'; + return false; + } foreach (array( 'sort' => 'sort', @@ -440,13 +559,9 @@ class DynamicListItem extends VerySimpleModel { 'abbrev' => 'extra') as $k => $v) { if (isset($vars[$k])) $this->set($v, $vars[$k]); - } - if ($save) - $this->save(); - - return true; + return $this->save(); } function delete() { @@ -471,9 +586,13 @@ class TicketStatusList extends BuiltInCustomList { 'name' => 'Status', 'name_plural' => 'Statuses', ); + // Fields of interest we need to store static $config_fields = array('sort_mode', 'notes'); + var $_items; + var $_form; + function getId() { return $this->ht['id']; } diff --git a/include/staff/dynamic-list.inc.php b/include/staff/dynamic-list.inc.php index ad0e8d29d2bcd2e46b8e5710a51909c607f16850..ef9f9c5a02c594aa55926bbb9eedffff674522d5 100644 --- a/include/staff/dynamic-list.inc.php +++ b/include/staff/dynamic-list.inc.php @@ -22,7 +22,7 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info) <input type="hidden" name="do" value="<?php echo $action; ?>"> <input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>"> <input type="hidden" name="id" value="<?php echo $info['id']; ?>"> - <h2>Custom List: <?php echo $list->getName(); ?></h2> + <h2>Custom List: <?php echo $list ? $list->getName() : 'Add new list'; ?></h2> <ul class="tabs"> <li><a href="#definition" class="active"> @@ -48,8 +48,8 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info) <td width="180" class="required">Name:</td> <td> <?php - if ($list->isBuiltIn()) - echo $info['name']; + if ($list && $list->isBuiltIn()) + echo $list->getName(); else { echo sprintf('<input size="50" type="text" name="name" value="%s"/> <span @@ -63,8 +63,8 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info) <td width="180">Plural Name:</td> <td> <?php - if ($list->isBuiltIn()) - echo $info['name_plural']; + if ($list && $list->isBuiltIn()) + echo $list->getPluralName(); else echo sprintf('<input size="50" type="text" name="name_plural" value="%s"/>', @@ -75,7 +75,9 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info) <tr> <td width="180">Sort Order:</td> <td><select name="sort_mode"> - <?php foreach ($list->getSortModes() as $key=>$desc) { ?> + <?php + $sortModes = $list ? $list->getSortModes() : DynamicList::getSortModes(); + foreach ($sortModes as $key=>$desc) { ?> <option value="<?php echo $key; ?>" <?php if ($key == $info['sort_mode']) echo 'selected="selected"'; ?>><?php echo $desc; ?></option> @@ -115,7 +117,7 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info) </tr> </thead> <tbody class="sortable-rows" data-sort="prop-sort-"> - <?php if ($form) foreach ($form->getDynamicFields() as $f) { + <?php if ($list && $form=$list->getForm()) foreach ($form->getDynamicFields() as $f) { $id = $f->get('id'); $deletable = !$f->isDeletable() ? 'disabled="disabled"' : ''; $force_name = $f->isNameForced() ? 'disabled="disabled"' : ''; @@ -129,7 +131,7 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info) if ($ferrors['label']) echo '<br/>'; echo $ferrors['label']; ?> </td> <td nowrap><select name="type-<?php echo $id; ?>" <?php - if (!$fi->isChangeable()) echo 'disabled="disabled"'; ?>> + if (!$fi->isChangeable() || !$f->isChangeable()) echo 'disabled="disabled"'; ?>> <?php foreach (FormField::allTypes() as $group=>$types) { ?><optgroup label="<?php echo Format::htmlchars($group); ?>"><?php foreach ($types as $type=>$nfo) { @@ -148,6 +150,7 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info) echo $f->get('id'); ?>" onclick="javascript: $('#overlay').show(); + $('#field-config .body').html('Loading...'); $('#field-config .body').load($(this).attr('href').substr(1)); $('#field-config').show(); return false; @@ -161,8 +164,13 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info) if ($ferrors['name']) echo '<br/>'; echo $ferrors['name']; ?></font> </td> - <td><input type="checkbox" name="delete-<?php echo $id; ?>" - <?php echo $deletable; ?>/> + <td> + <?php + if (!$f->isDeletable()) + echo '<i class="icon-ban-circle"></i>'; + else + echo sprintf('<input type="checkbox" name="delete-prop-%s">', $id); + ?> <input type="hidden" name="prop-sort-<?php echo $id; ?>" value="<?php echo $f->get('sort'); ?>"/> </td> @@ -220,7 +228,11 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info) <tr> <th></th> <th>Value</th> + <?php + if (!$list || !$list->isBuiltIn()) { ?> <th>Abbrev <em style="display:inline">— Abbreviations and such</em></th> + <?php + } ?> <th>Disabled</th> <th>Delete</th> </tr> @@ -242,22 +254,51 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info) value="<?php echo $i->getValue(); ?>"/> <?php if ($list->hasProperties()) { ?> <a class="action-button" style="float:none;overflow:inherit" - href="#ajax.php/list/item/<?php - echo $id ?>/properties" + href="#ajax.php/list/<?php + echo $list->getId(); ?>/item/<?php echo $id ?>/properties" onclick="javascript: $('#overlay').show(); + $('#field-config .body').html('Loading...'); $('#field-config .body').load($(this).attr('href').substr(1)); $('#field-config').show(); return false; "><i class="icon-edit"></i> Properties</a> - <?php } ?></td> + <?php + } + + if ($errors["value-$id"]) + echo sprintf('<br><span class="error">%s</span>', + $errors["value-$id"]); + ?> + </td> + <?php + if (!$list->isBuiltIn()) { ?> <td><input type="text" size="30" name="abbrev-<?php echo $id; ?>" value="<?php echo $i->getAbbrev(); ?>"/></td> + <?php + } ?> <td> - <input type="checkbox" name="disable-<?php echo $id; ?>" <?php - if (!$i->isEnabled()) echo 'checked="checked"'; ?>/></td> + <?php + if ($i->isInternal()) + echo '<i class="icon-ban-circle"></i>'; + else + echo sprintf('<input type="checkbox" name="disable-%s" + %s %s />', + $id, + !$i->isEnabled() ? ' checked="checked" ' : '', + (!$i->isEnabled() && !$i->isEnableable()) ? ' disabled="disabled" ' : '' + ); + ?> + </td> <td> - <input type="checkbox" name="delete-<?php echo $id; ?>"/></td> + <?php + if (!$i->isDeletable()) + echo '<i class="icon-ban-circle"></i>'; + else + echo sprintf('<input type="checkbox" name="delete-item-%s">', $id); + + ?> + </td> </tr> <?php } } @@ -266,9 +307,13 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info) <td><?php echo $icon; ?> <em>+</em> <input type="hidden" name="sort-new-<?php echo $i; ?>"/></td> <td><input type="text" size="40" name="value-new-<?php echo $i; ?>"/></td> + <?php + if (!$list || !$list->isBuiltIn()) { ?> <td><input type="text" size="30" name="abbrev-new-<?php echo $i; ?>"/></td> - <td></td> - <td></td> + <?php + } ?> + <td> </td> + <td> </td> </tr> <?php } ?> </tbody> diff --git a/include/staff/templates/list-item-properties.tmpl.php b/include/staff/templates/list-item-properties.tmpl.php index ce4a0ca5ee64aeb1ccef1914cea444f21f1c1390..ef7158d03c78fb746cb100575bc54b34ab65f722 100644 --- a/include/staff/templates/list-item-properties.tmpl.php +++ b/include/staff/templates/list-item-properties.tmpl.php @@ -1,8 +1,9 @@ - <h3>Item Properties — <?php echo $item->get('value') ?></h3> + <h3>Item Properties — <?php echo $item->getValue(); ?></h3> <a class="close" href=""><i class="icon-remove-circle"></i></a> <hr/> - <form method="post" action="ajax.php/list/item/<?php - echo $item->get('id'); ?>/properties" onsubmit="javascript: + <form method="post" action="ajax.php/list/<?php + echo $list->getId(); ?>/item/<?php + echo $item->getId(); ?>/properties" onsubmit="javascript: var form = $(this); $.post(this.action, form.serialize(), function(data, status, xhr) { if (!data.length) { diff --git a/scp/ajax.php b/scp/ajax.php index a192cce8cf92da76bf185a441840093133d03099..0cf11d7d46d541eeba4521d412ee4f62b78b4844 100644 --- a/scp/ajax.php +++ b/scp/ajax.php @@ -57,8 +57,8 @@ $dispatcher = patterns('', url_delete('^answer/(?P<entry>\d+)/(?P<field>\d+)$', 'deleteAnswer') )), url('^/list/', patterns('ajax.forms.php:DynamicFormsAjaxAPI', - url_get('^item/(?P<id>\d+)/properties$', 'getListItemProperties'), - url_post('^item/(?P<id>\d+)/properties$', 'saveListItemProperties') + url_get('^(?P<list>\w+)/item/(?P<id>\d+)/properties$', 'getListItemProperties'), + url_post('^(?P<list>\w+)/item/(?P<id>\d+)/properties$', 'saveListItemProperties') )), url('^/report/overview/', patterns('ajax.reports.php:OverviewReportAjaxAPI', # Send diff --git a/scp/lists.php b/scp/lists.php index 56232c76c3c482da7abb8092c3a52daed7ee0a8e..84fe3bdc600274e58e371a430cab28affe082d09 100644 --- a/scp/lists.php +++ b/scp/lists.php @@ -16,112 +16,108 @@ if ($_REQUEST['id']) { $errors['err'] = 'Unknown or invalid dynamic list ID.'; } +$errors = array(); +$max_isort = 0; + if($_POST) { - $fields = array('name', 'name_plural', 'sort_mode', 'notes'); - $required = array('name'); switch(strtolower($_POST['do'])) { case 'update': - if ($list->update($_POST, $errors)) - $msg = 'Custom list updated successfully'; - elseif ($errors) - $errors['err'] = 'Unable to update custom list. Correct any error(s) below and try again.'; - else - $errors['err'] = 'Unable to update custom list. Unknown internal error'; - - if ($list->getNumItems()) { + if (!$list) + $errors['err'] = 'Unknown or invalid list'; + elseif ($list->update($_POST, $errors)) { + // Update items + $items = array(); foreach ($list->getAllItems() as $item) { $id = $item->getId(); - if ($_POST["delete-$id"] == 'on') { + if ($_POST["delete-item-$id"] == 'on' && $item->isDeletable()) { $item->delete(); continue; } - $item->update(array( - 'value' => $_POST["value-$id"], - 'abbrev' => $_POST["abbrev-$id"], - 'sort' => $_POST["name-$id"], - ), - false); - - if ($_POST["disable-$id"] == 'on') - $item->disable(); - else - $item->enable(); + $ht = array( + 'value' => $_POST["value-$id"], + 'abbrev' => $_POST["abbrev-$id"], + 'sort' => $_POST["sort-$id"], + ); + $value = mb_strtolower($ht['value']); + if (!$value) + $errors["value-$id"] = 'Value required'; + elseif (in_array($value, $items)) + $errors["value-$id"] = 'Value already in-use'; + elseif ($item->update($ht, $errors)) { + if ($_POST["disable-$id"] == 'on') + $item->disable(); + elseif(!$item->isEnabled() && $item->isEnableable()) + $item->enable(); + + $item->save(); + $items[] = $value; + } - $item->save(); + $max_isort = max($max_isort, $_POST["sort-$id"]); } - } - $names = array(); - if (!$form) { - $form = DynamicForm::create(array( - 'type' => 'L'.$list->getId(), - 'title' => $list->getName() . ' Properties' - )); - $form->save(true); - } - foreach ($form->getDynamicFields() as $field) { - $id = $field->get('id'); - if ($_POST["delete-$id"] == 'on' && $field->isDeletable()) { - $field->delete(); - // Don't bother updating the field - continue; - } - if (isset($_POST["type-$id"]) && $field->isChangeable()) - $field->set('type', $_POST["type-$id"]); - if (isset($_POST["name-$id"]) && !$field->isNameForced()) - $field->set('name', $_POST["name-$id"]); - # TODO: make sure all help topics still have all required fields - foreach (array('sort','label') as $f) { - if (isset($_POST["prop-$f-$id"])) { - $field->set($f, $_POST["prop-$f-$id"]); + // Update properties + if (!$errors && ($form = $list->getForm())) { + $names = array(); + foreach ($form->getDynamicFields() as $field) { + $id = $field->get('id'); + if ($_POST["delete-prop-$id"] == 'on' && $field->isDeletable()) { + $field->delete(); + // Don't bother updating the field + continue; + } + if (isset($_POST["type-$id"]) && $field->isChangeable()) + $field->set('type', $_POST["type-$id"]); + if (isset($_POST["name-$id"]) && !$field->isNameForced()) + $field->set('name', $_POST["name-$id"]); + + foreach (array('sort','label') as $f) { + if (isset($_POST["prop-$f-$id"])) { + $field->set($f, $_POST["prop-$f-$id"]); + } + } + if (in_array($field->get('name'), $names)) + $field->addError('Field variable name is not unique', 'name'); + if (preg_match('/[.{}\'"`; ]/u', $field->get('name'))) + $field->addError('Invalid character in variable name. Please use letters and numbers only.', 'name'); + if ($field->get('name')) + $names[] = $field->get('name'); + if ($field->isValid()) + $field->save(); + else + # notrans (not shown) + $errors["field-$id"] = 'Field has validation errors'; + // Keep track of the last sort number + $max_sort = max($max_sort, $field->get('sort')); } } - if (in_array($field->get('name'), $names)) - $field->addError('Field variable name is not unique', 'name'); - if (preg_match('/[.{}\'"`; ]/u', $field->get('name'))) - $field->addError('Invalid character in variable name. Please use letters and numbers only.', 'name'); - if ($field->get('name')) - $names[] = $field->get('name'); - if ($field->isValid()) - $field->save(); + + if ($errors) + $errors['err'] = $errors['err'] ?: 'Unable to update custom list items. Correct any error(s) and try again.'; else - # notrans (not shown) - $errors["field-$id"] = 'Field has validation errors'; - // Keep track of the last sort number - $max_sort = max($max_sort, $field->get('sort')); - } + $msg = 'Custom list updated successfully'; + + } elseif ($errors) + $errors['err'] = 'Unable to update custom list. Correct any error(s) below and try again.'; + else + $errors['err'] = 'Unable to update custom list. Unknown internal error'; + break; case 'add': - foreach ($fields as $f) - if (in_array($f, $required) && !$_POST[$f]) - $errors[$f] = sprintf('%s is required', - mb_convert_case($f, MB_CASE_TITLE)); - $list = DynamicList::create(array( - 'name'=>$_POST['name'], - 'name_plural'=>$_POST['name_plural'], - 'sort_mode'=>$_POST['sort_mode'], - 'notes'=>$_POST['notes'])); - - $form = DynamicForm::create(array( - 'title'=>$_POST['name'] . ' Properties' - )); - - if ($errors) - $errors['err'] = 'Unable to create custom list. Correct any error(s) below and try again.'; - elseif (!$list->save(true)) + if ($list=DynamicList::add($_POST, $errors)) { + $msg = 'Custom list added successfully'; + } elseif ($errors) { + $errors['err'] = 'Unable to create custom list. Correct any + error(s) below and try again.'; + } else { $errors['err'] = 'Unable to create custom list: Unknown internal error'; - - $form->set('type', 'L'.$list->get('id')); - if (!$errors && !$form->save(true)) - $errors['err'] = 'Unable to create properties for custom list: Unknown internal error'; - else - $msg = 'Custom list added successfully'; + } break; case 'mass_process': if(!$_POST['ids'] || !is_array($_POST['ids']) || !count($_POST['ids'])) { - $errors['err'] = 'You must select at least one API key'; + $errors['err'] = 'You must select at least one custom list'; } else { $count = count($_POST['ids']); switch(strtolower($_POST['a'])) { @@ -152,8 +148,8 @@ if($_POST) { $list->addItem(array( 'value' => $_POST["value-new-$i"], 'abbrev' =>$_POST["abbrev-new-$i"], - 'sort' => $_POST["sort-new-$i"] - )); + 'sort' => $_POST["sort-new-$i"] ?: ++$max_isort, + ), $errors); } } @@ -162,12 +158,11 @@ if($_POST) { if (!$_POST["prop-label-new-$i"]) continue; $field = DynamicFormField::create(array( - 'form_id'=>$form->get('id'), - 'sort'=>$_POST["prop-sort-new-$i"] - ? $_POST["prop-sort-new-$i"] : ++$max_sort, - 'label'=>$_POST["prop-label-new-$i"], - 'type'=>$_POST["type-new-$i"], - 'name'=>$_POST["name-new-$i"], + 'form_id' => $form->get('id'), + 'sort' => $_POST["prop-sort-new-$i"] ?: ++$max_sort, + 'label' => $_POST["prop-label-new-$i"], + 'type' => $_POST["type-new-$i"], + 'name' => $_POST["name-new-$i"], )); $field->setForm($form); if ($field->isValid())