DataTypeDatalist: allow to customize behavior
Available options: * strict: select box * suggest_strict: auto-completion, allow only list values * suggest_optional: Allow for values not on the list * suggest_extend: Extend the list with new values fixes #1846
This commit is contained in:
parent
7177d489ec
commit
db8895ae10
|
@ -258,6 +258,22 @@ class SuggestController extends ActionController
|
|||
]);
|
||||
}
|
||||
|
||||
protected function suggestDataListValuesForListId($id)
|
||||
{
|
||||
$db = $this->db()->getDbAdapter();
|
||||
$select = $db->select()
|
||||
->from('director_datalist_entry', ['entry_name', 'entry_value'])
|
||||
->where('list_id = ?', $id)
|
||||
->order('entry_value ASC');
|
||||
|
||||
$result = $db->fetchPairs($select);
|
||||
if ($result) {
|
||||
return $result;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
protected function suggestDataListValues($field = null)
|
||||
{
|
||||
if ($field === null) {
|
||||
|
|
|
@ -3,28 +3,87 @@
|
|||
namespace Icinga\Module\Director\DataType;
|
||||
|
||||
use Icinga\Module\Director\Acl;
|
||||
use Icinga\Module\Director\Db;
|
||||
use Icinga\Module\Director\Hook\DataTypeHook;
|
||||
use Icinga\Module\Director\Objects\DirectorDatalistEntry;
|
||||
use Icinga\Module\Director\Web\Form\DirectorForm;
|
||||
use Icinga\Module\Director\Web\Form\QuickForm;
|
||||
use Icinga\Module\Director\Web\Form\DirectorObjectForm;
|
||||
use Icinga\Module\Director\Web\Form\Validate\IsDataListEntry;
|
||||
|
||||
class DataTypeDatalist extends DataTypeHook
|
||||
{
|
||||
/**
|
||||
* @param $name
|
||||
* @param QuickForm $form
|
||||
* @return \Zend_Form_Element
|
||||
* @throws \Zend_Form_Exception
|
||||
*/
|
||||
public function getFormElement($name, QuickForm $form)
|
||||
{
|
||||
$enum = $this->getEntries($form);
|
||||
$params = [];
|
||||
if ($this->getSetting('data_type') === 'array') {
|
||||
$type = 'extensibleSet';
|
||||
$params['sorted'] = true;
|
||||
$params = ['multiOptions' => $enum];
|
||||
$behavior = $this->getSetting('behavior', 'strict');
|
||||
$targetDataType = $this->getSetting('data_type');
|
||||
$listId = $this->getSetting('datalist_id');
|
||||
|
||||
if ($behavior === 'strict') {
|
||||
$enum = $this->getEntries($form);
|
||||
if ($targetDataType === 'string') {
|
||||
$params['sorted'] = true;
|
||||
$params = ['multiOptions' => $enum];
|
||||
$type = 'select';
|
||||
} else {
|
||||
$params = ['multiOptions' => $form->optionalEnum($enum)];
|
||||
$type = 'extensibleSet';
|
||||
}
|
||||
} else {
|
||||
$params = ['multiOptions' => [
|
||||
null => $form->translate('- please choose -'),
|
||||
] + $enum];
|
||||
$type = 'select';
|
||||
if ($targetDataType === 'string') {
|
||||
$type = 'text';
|
||||
} else {
|
||||
$type = 'extensibleSet';
|
||||
}
|
||||
$params['class'] = 'director-suggest';
|
||||
$params['data-suggestion-context'] = "dataListValuesForListId!$listId";
|
||||
}
|
||||
$element = $form->createElement($type, $name, $params);
|
||||
if ($behavior === 'suggest_strict') {
|
||||
$element->addValidator(new IsDataListEntry($listId, $form->getDb()));
|
||||
}
|
||||
|
||||
return $form->createElement($type, $name, $params);
|
||||
if ($behavior === 'suggest_extend') {
|
||||
$form->callOnSucess(function (DirectorForm $form) use ($name, $listId) {
|
||||
$value = (array) $form->getValue($name);
|
||||
if ($value === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$db = $form->getDb();
|
||||
foreach ($value as $entry) {
|
||||
$this->createEntryIfNotExists($db, $listId, $entry);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Db $db
|
||||
* @param $listId
|
||||
* @param $entry
|
||||
*/
|
||||
protected function createEntryIfNotExists(Db $db, $listId, $entry)
|
||||
{
|
||||
if (! DirectorDatalistEntry::exists([
|
||||
'list_id' => $listId,
|
||||
'entry_name' => $entry,
|
||||
], $db)) {
|
||||
DirectorDatalistEntry::create([
|
||||
'list_id' => $listId,
|
||||
'entry_name' => $entry,
|
||||
'entry_value' => $entry,
|
||||
])->store($db);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getEntries(QuickForm $form)
|
||||
|
@ -34,7 +93,7 @@ class DataTypeDatalist extends DataTypeHook
|
|||
|
||||
$roles = array_map('json_encode', Acl::instance()->listRoleNames());
|
||||
$select = $db->select()
|
||||
->from('director_datalist_entry', array('entry_name', 'entry_value'))
|
||||
->from('director_datalist_entry', ['entry_name', 'entry_value'])
|
||||
->where('list_id = ?', $this->getSetting('datalist_id'))
|
||||
->order('entry_value ASC');
|
||||
|
||||
|
@ -47,17 +106,20 @@ class DataTypeDatalist extends DataTypeHook
|
|||
return $db->fetchPairs($select);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param QuickForm $form
|
||||
* @throws \Zend_Form_Exception
|
||||
*/
|
||||
public static function addSettingsFormFields(QuickForm $form)
|
||||
{
|
||||
/** @var DirectorObjectForm $form */
|
||||
$db = $form->getDb();
|
||||
|
||||
$form->addElement('select', 'datalist_id', array(
|
||||
$form->addElement('select', 'datalist_id', [
|
||||
'label' => 'List name',
|
||||
'required' => true,
|
||||
'multiOptions' => array(null => '- please choose -') +
|
||||
$db->enumDatalist(),
|
||||
));
|
||||
'multiOptions' => $form->optionalEnum($db->enumDatalist()),
|
||||
]);
|
||||
|
||||
$form->addElement('select', 'data_type', [
|
||||
'label' => $form->translate('Target data type'),
|
||||
|
@ -68,6 +130,20 @@ class DataTypeDatalist extends DataTypeHook
|
|||
'required' => true,
|
||||
]);
|
||||
|
||||
return $form;
|
||||
$form->addElement('select', 'behavior', [
|
||||
'label' => $form->translate('Element behavior'),
|
||||
'value' => 'strict',
|
||||
'description' => $form->translate(
|
||||
'This allows to show either a drop-down list or an auto-completion'
|
||||
),
|
||||
'multiOptions' => [
|
||||
'strict' => $form->translate('Dropdown (list values only)'),
|
||||
$form->translate('Autocomplete') => [
|
||||
'suggest_strict' => $form->translate('Strict, list values only'),
|
||||
'suggest_optional' => $form->translate('Allow for values not on the list'),
|
||||
'suggest_extend' => $form->translate('Extend the list with new values'),
|
||||
]
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Module\Director\Web\Form\Validate;
|
||||
|
||||
use Icinga\Module\Director\Db;
|
||||
use Icinga\Module\Director\Objects\DirectorDatalistEntry;
|
||||
use Zend_Validate_Abstract;
|
||||
|
||||
class IsDataListEntry extends Zend_Validate_Abstract
|
||||
{
|
||||
const INVALID = 'intInvalid';
|
||||
|
||||
/** @var Db */
|
||||
private $db;
|
||||
|
||||
/** @var int */
|
||||
private $dataListId;
|
||||
|
||||
public function __construct($dataListId, Db $db)
|
||||
{
|
||||
$this->db = $db;
|
||||
$this->dataListId = (int) $dataListId;
|
||||
}
|
||||
|
||||
public function isValid($value)
|
||||
{
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $name) {
|
||||
if (! $this->isListEntry($name)) {
|
||||
$this->_error(self::INVALID, $value);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->isListEntry($value)) {
|
||||
return true;
|
||||
} else {
|
||||
$this->_error(self::INVALID, $value);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function isListEntry($name)
|
||||
{
|
||||
return DirectorDatalistEntry::exists([
|
||||
'list_id' => $this->dataListId,
|
||||
'entry_name' => $name,
|
||||
], $this->db);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue