Newer
Older
'field' => array(
'constraint' => array('field_id' => 'DynamicFormField.id'),
),
'entry' => array(
'constraint' => array('entry_id' => 'DynamicFormEntry.id'),
),
),
);
var $deleted = false;
var $_value;
function getEntry() {
return $this->entry;
}
function getForm() {
if (!$this->form)
$this->form = $this->getEntry()->getForm();
return $this->form;
}
function getField() {
if (!isset($this->_field)) {
$this->_field = $this->field->getImpl($this->field);
$this->_field->setAnswer($this);
return $this->_field;
if (!$this->_value && isset($this->value))
$this->_value = $this->getField()->to_php(
$this->get('value'), $this->get('value_id'));
return $this->_value;
function getIdValue() {
return $this->get('value_id');
}
function isDeleted() {
return $this->deleted;
}
function toString() {
return $this->getField()->toString($this->getValue());
}
function display() {
return $this->getField()->display($this->getValue());
}
function getSearchable($include_label=false) {
if ($include_label)
$label = Format::searchable($this->getField()->getLabel()) . " ";
return sprintf("%s%s", $label,
$this->getField()->searchable($this->getValue())
);
}
function getSearchKeys() {
$val = $this->getField()->to_php(
$this->get('value'), $this->get('value_id'));
if (is_array($val))
return array_keys($val);
elseif (is_object($val) && method_exists($val, 'getId'))
return array($val->getId());
return (is_object($this->getValue()))
? $this->getValue() : $this->toString();
}
function getVar($tag) {
if (is_object($this->getValue()) && method_exists($this->getValue(), 'getVar'))
return $this->getValue()->getVar($tag);
function __toString() {
$v = $this->toString();
return is_string($v) ? $v : (string) $this->getValue();
}
class SelectionField extends FormField {
static $widget = 'ChoicesWidget';
function getListId() {
list(,$list_id) = explode('-', $this->get('type'));
return $list_id ?: $this->get('list_id');
if (!$this->_list)
$this->_list = DynamicList::lookup($this->getListId());
function getWidget() {
$config = $this->getConfiguration();
$widgetClass = false;
if ($config['widget'] == 'typeahead' && $config['multiselect'] == false)
$widgetClass = 'TypeaheadSelectionWidget';
return parent::getWidget($widgetClass);
}
if (!($list=$this->getList()))
return null;
$config = $this->getConfiguration();
$choices = $this->getChoices();
$selection = array();
if ($value && is_array($value)) {
foreach ($value as $k=>$v) {
if (($i=$list->getItem((int) $k)))
$selection[$i->getId()] = $i->getValue();
elseif (isset($choices[$v]))
$selection[$v] = $choices[$v];
}
}
return $selection;
}
function to_database($value) {
if (is_array($value)) {
reset($value);
}
if ($value && is_array($value))
$value = JsonDataEncoder::encode($value);
return $value;
function to_php($value, $id=false) {
if (is_string($value))
$value = JsonDataParser::parse($value) ?: $value;
if (!is_array($value)) {
$config = $this->getConfiguration();
if (!$config['multiselect']) {
// CDATA may be built with comma-list
list($value,) = explode(',', $value, 2);
}
$choices = $this->getChoices();
if (isset($choices[$value]))
$value = array($value => $choices[$value]);
elseif ($id && isset($choices[$id]))
$value = array($id => $choices[$id]);
// Don't set the ID here as multiselect prevents using exactly one
// ID value. Instead, stick with the JSON value only.
return $this->getList()->getForm();
$form = $this->getList()->getForm();
if ($form)
return $form->getFields();
return array();
function toString($items) {
return ($items && is_array($items))
? implode(', ', $items) : (string) $items;
function validateEntry($entry) {
parent::validateEntry($entry);
if (!$this->errors()) {
$config = $this->getConfiguration();
if ($config['typeahead']
&& ($entered = $this->getWidget()->getEnteredValue())
&& !in_array($entered, $entry))
$this->_errors[] = __('Select a value from the list');
}
function getConfigurationOptions() {
return array(
'multiselect' => new BooleanField(array(
'id'=>2,
'label'=>__(/* Type of widget allowing multiple selections */ 'Multiselect'),
'required'=>false, 'default'=>false,
'configuration'=>array(
'desc'=>__('Allow multiple selections')),
)),
'id'=>1,
'label'=>__('Widget'),
'required'=>false, 'default' => 'dropdown',
'dropdown' => __('Drop Down'),
'typeahead' =>__('Typeahead'),
),
'configuration'=>array(
'multiselect' => false,
),
'visibility' => new VisibilityConstraint(
new Q(array('multiselect__eq'=>false)),
VisibilityConstraint::HIDDEN
),
'hint'=>__('Typeahead will work better for large lists')
'id'=>3,
'label'=>__('Prompt'), 'required'=>false, 'default'=>'',
'hint'=>__('Leading text shown before a value is selected'),
'configuration'=>array('size'=>40, 'length'=>40,
'translatable'=>$this->getTranslateTag('prompt'),
),
'default' => new SelectionField(array(
'id'=>4, 'label'=>__('Default'), 'required'=>false, 'default'=>'',
'list_id'=>$this->getListId(),
'configuration' => array('prompt'=>__('Select a Default')),
)),
function getConfiguration() {
$config = parent::getConfiguration();
if ($config['widget'])
$config['typeahead'] = $config['widget'] == 'typeahead';
// Drop down list does not support multiple selections
if ($config['typeahead'])
$config['multiselect'] = false;
return $config;
}
function getChoices($verbose=false) {
if (!$this->_choices || $verbose) {
$this->_choices = array();
foreach ($this->getList()->getItems() as $i)
$this->_choices[$i->getId()] = $i->getValue();
// Retired old selections
$values = ($a=$this->getAnswer()) ? $a->getValue() : array();
if ($values && is_array($values)) {
foreach ($values as $k => $v) {
if (!isset($this->_choices[$k])) {
if ($verbose) $v .= ' '.__('(retired)');
}
return $this->_choices;
}
function getChoice($value) {
$choices = $this->getChoices();
if ($value && is_array($value)) {
$selection = $value;
} elseif (isset($choices[$value]))
$selection[] = $choices[$value];
elseif ($this->get('default'))
$selection[] = $choices[$this->get('default')];
return $selection;
}
function export($value) {
if ($value && is_numeric($value)
&& ($item = DynamicListItem::lookup($value)))
return $item->toString();
return $value;
}
function getFilterData() {
$data = array(parent::getFilterData());
if (($v = $this->getClean()) instanceof DynamicListItem) {
$data = array_merge($data, $v->getFilterData());
}
return $data;
}
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
function getSearchMethods() {
return array(
'set' => __('has a value'),
'notset' => __('does not have a value'),
'includes' => __('includes'),
'!includes' => __('does not include'),
);
}
function getSearchMethodWidgets() {
return array(
'set' => null,
'notset' => null,
'includes' => array('ChoiceField', array(
'choices' => $this->getChoices(),
'configuration' => array('multiselect' => true),
)),
'!includes' => array('ChoiceField', array(
'choices' => $this->getChoices(),
'configuration' => array('multiselect' => true),
)),
);
}
function getSearchQ($method, $value, $name=false) {
$name = $name ?: $this->get('name');
switch ($method) {
case '!includes':
return Q::not(array("{$name}__intersect" => array_keys($value)));
return new Q(array("{$name}__intersect" => array_keys($value)));
default:
return parent::getSearchQ($method, $value, $name);
}
}
class TypeaheadSelectionWidget extends ChoicesWidget {
function render($how) {
if ($how == 'search')
return parent::render($how);
$name = $this->getEnteredValue();
$config = $this->field->getConfiguration();
if (is_array($this->value)) {
$name = $name ?: current($this->value);
$value = key($this->value);
else {
// Pull configured default (if configured)
$def_key = $this->field->get('default');
if (!$def_key && $config['default'])
$def_key = $config['default'];
if (is_array($def_key))
$name = current($def_key);
}
$source = array();
foreach ($this->field->getList()->getItems() as $i)
$source[] = array(
'value' => $i->getValue(), 'id' => $i->getId(),
'info' => sprintf('%s %s',
$i->getValue(),
(($extra= $i->getAbbrev()) ? "-- $extra" : '')),
<input type="text" size="30" name="<?php echo $this->name; ?>_name"
id="<?php echo $this->name; ?>" value="<?php echo Format::htmlchars($name); ?>"
placeholder="<?php echo $config['prompt'];
?>" autocomplete="off" />
<input type="hidden" name="<?php echo $this->name;
?>[<?php echo $value; ?>]" id="<?php echo $this->name;
?>_id" value="<?php echo Format::htmlchars($name); ?>"/>
<script type="text/javascript">
$(function() {
$('input#<?php echo $this->name; ?>').typeahead({
source: <?php echo JsonDataEncoder::encode($source); ?>,
$('input#<?php echo $this->name; ?>_name').val(item['value'])
$('input#<?php echo $this->name; ?>_id')
.attr('name', '<?php echo $this->name; ?>[' + item['id'] + ']')
.val(item['value']);
}
});
});
</script>
</span>
<?php
}
function getValue() {
$data = $this->field->getSource();
if (isset($data[$this->name]))
return $data[$this->name];
return parent::getValue();
}
function getEnteredValue() {
// Used to verify typeahead fields
$data = $this->field->getSource();
if (isset($data[$this->name.'_name']))
return trim($data[$this->name.'_name']);
return parent::getValue();
}