(mixed) custom id attribute value
* if numeric value is passed it'll be just appended to the name e.g. {filed-name}-{value}
* if false is passed id will be not created
* if empty string is passed (or no 'id' option is found)
* in all other cases the value will be used as field id
* default: empty string
*
* - class => (string) field class(es)
* Example: 'tbox select class1 class2 class3'
* NOTE: this will override core classes, so you have to explicit include them!
* default: empty string
*
* - size => (int) size attribute value (used when needed)
* default: 40
*
* - title (string) title attribute
* default: empty string (omitted)
*
* - readonly => (bool) readonly attribute
* default: false
*
* - selected => (bool) selected attribute (used when needed)
* default: false
*
* checked => (bool) checked attribute (used when needed)
* default: false
* - disabled => (bool) disabled attribute
* default: false
*
* - tabindex => (int) tabindex attribute value
* default: inner tabindex counter
*
* - other => (string) additional data
* Example: 'attribute1="value1" attribute2="value2"'
* default: empty string
*/
class e_form
{
protected $_tabindex_counter = 0;
protected $_tabindex_enabled = true;
protected $_cached_attributes = array();
/**
* @var user_class
*/
protected $_uc;
function __construct($enable_tabindex = false)
{
$this->_tabindex_enabled = $enable_tabindex;
$this->_uc = e107::getUserClass();
}
function text($name, $value, $maxlength = 200, $options = array())
{
$options = $this->format_options('text', $name, $options);
//never allow id in format name-value for text fields
return "get_attributes($options, $name)." />";
}
function iconpreview($id, $default, $width='', $height='') // FIXME
{
$parms = $name."|".$width."|".$height."|".$id;
$sc_parameters .= 'mode=preview&default='.$default.'&id='.$id;
return e107::getParser()->parseTemplate("{ICONPICKER=".$sc_parameters."}");
}
function iconpicker($name, $default, $label, $sc_parameters = '', $ajax = true)
{
// TODO - Hide the element, and display the icon itself after it has been chosen.
// eg.
// The button itself could be replaced with an icon just for this purpose.
$e107 = e107::getInstance();
$id = $this->name2id($name);
$sc_parameters .= '&id='.$id;
$jsfunc = $ajax ? "e107Ajax.toggleUpdate('{$id}-iconpicker', '{$id}-iconpicker-cn', 'sc:iconpicker=".urlencode($sc_parameters)."', '{$id}-iconpicker-ajax', { overlayElement: '{$id}-iconpicker-button' })" : "e107Helper.toggle('{$id}-iconpicker')";
$ret = $this->text($name, $default);
// $ret .= $this->iconpreview($id,$default); //FIXME
$ret .= $this->admin_button($name.'-iconpicker-button', $label, 'action', '', array('other' => "onclick=\"{$jsfunc}\""));
$ret .= "
";
continue;
}
$tdclass = vartrue($data['class']);
if($field == 'checkboxes') $tdclass = $tdclass ? $tdclass.' autocheck e-pointer' : 'autocheck e-pointer';
// there is no other way for now - prepare user data
if('user' == $data['type']/* && isset($data['readParms']['idField'])*/)
{
if(is_string($data['readParms'])) parse_str($data['readParms'], $data['readParms']);
if(isset($data['readParms']['idField']))
{
$data['readParms']['__idval'] = $fieldvalues[$data['readParms']['idField']];
}
}
$value = $this->renderValue($field, varset($fieldvalues[$field]), $data, varset($fieldvalues[$pid]));
if($tdclass)
{
$tdclass = ' class="'.$tdclass.'"';
}
$ret .= '
'.$value.'
';
$cnt++;
}
if($cnt)
{
return '
'.$ret.'
';
}
return '';
}
/**
* Render Field Value
* @param string $field field name
* @param mixed $value field value
* @param array $attributes field attributes including render parameters, element options - see e_admin_ui::$fields for required format
* @return string
*/
function renderValue($field, $value, $attributes, $id = 0)
{
$parms = array();
if(isset($attributes['readParms']))
{
if(is_string($attributes['readParms'])) parse_str($attributes['readParms'], $attributes['readParms']);
$parms = $attributes['readParms'];
}
$tp = e107::getParser();
switch($field) // special fields
{
case 'options':
if(!$value)
{
parse_str(str_replace('&', '&', e_QUERY), $query); //FIXME - FIX THIS
// keep other vars in tact
$query['action'] = 'edit';
$query['id'] = $id;
//$edit_query = array('mode' => varset($query['mode']), 'action' => varset($query['action']), 'id' => $id);
$query = http_build_query($query);
$value = " ";
$value .= $this->submit_image('etrigger_delete['.$id.']', $id, 'delete', LAN_DELETE.' [ ID: '.$id.' ]');
}
//$attributes['type'] = 'text';
return $value;
break;
case 'checkboxes':
$value = $this->checkbox(vartrue($attributes['toggle'], 'multiselect').'['.$id.']', $id);
//$attributes['type'] = 'text';
return $value;
break;
}
switch($attributes['type'])
{
case 'number':
if($parms)
{
if(!isset($parms['sep'])) $value = number_format($number, $parms['decimals']);
else $value = number_format($number, $parms['decimals'], vartrue($parms['point'], '.'), vartrue($parms['sep'], ' '));
}
$value = vartrue($parms['pre']).$value.vartrue($parms['post']);
// else same
break;
case 'ip':
$e107 = e107::getInstance();
$value = $e107->ipDecode($value);
// else same
break;
case 'dropdown':
case 'text':
if(vartrue($parms['truncate']))
{
$value = $tp->text_truncate($value, $parms['truncate'], '...');
}
elseif(vartrue($parms['htmltruncate']))
{
$value = $tp->html_truncate($value, $parms['htmltruncate'], '...');
}
$value = vartrue($parms['pre']).$value.vartrue($parms['post']);
break;
case 'bbarea':
case 'textarea':
$expand = '...';
$toexpand = false;
if($attributes['type'] == 'bbarea' && !isset($parms['bb'])) $parms['bb'] = true; //force bb parsing for bbareas
$elid = trim(str_replace('_', '-', $field)).'-'.$id;
if(!vartrue($parms['noparse'])) $value = $tp->toHTML($value, (vartrue($parms['bb']) ? true : false), vartrue($parms['parse']));
if(vartrue($parms['expand']))
{
$expand = ' '.defset($parms['expand'], $parms['expand'])."";
}
$oldval = $value;
if(vartrue($parms['truncate']))
{
$value = $oldval = strip_tags($value);
$value = $tp->text_truncate($value, $parms['truncate'], $expand);
$toexpand = $value != $oldval;
}
elseif(vartrue($parms['htmltruncate']))
{
$value = $tp->html_truncate($value, $parms['htmltruncate'], $expand);
$toexpand = $value != $oldval;
}
if($toexpand)
{
// force hide! TODO - core style .expand-c (expand container)
$value .= '
'.$oldval.'
';
}
break;
case 'icon':
$value = '';
break;
case 'image': //TODO - thumb, js tooltip...
$ttl = vartrue($parms['title'], 'LAN_PREVIEW');
$value = ''.defset($ttl, $ttl).'';
break;
case 'datestamp':
$value = e107::getDateConvert()->convert_date($value, vartrue($parms['mask'], 'short'));
break;
case 'userclass':
$value = $this->_uc->uc_get_classname($value);
break;
case 'userclasses':
$classes = explode(',', $value);
$value = array();
foreach ($classes as $cid)
{
$value[] = $this->_uc->uc_get_classname($cid);
}
$value = implode(vartrue($parms['separator']), $pieces);
break;
/*case 'user_name':
case 'user_loginname':
case 'user_login':
case 'user_customtitle':
case 'user_email':*/
case 'user':
/*if(is_numeric($value))
{
$value = get_user_data($value);
if($value)
{
$value = $value[$attributes['type']] ? $value[$attributes['type']] : $value['user_name'];
}
else
{
$value = 'not found';
}
}*/
// Dirty, but the only way for now
if(vartrue($parms['__idval']) && vartrue($parms['link']))
{
$value = ''.$value.'';
}
break;
case 'boolean':
$value = $value ? ADMIN_TRUE_ICON : ADMIN_FALSE_ICON;
break;
case 'url':
$ttl = $value;
if(vartrue($parms['truncate']))
{
$ttl = $tp->text_truncate($value, $parms['truncate'], '...');
}
$value = "".$ttl."";
break;
case 'method': // Custom Function
$method = $field;
$value = call_user_func_array(array($this, $method), array($value, 'read', $parms));
break;
//TODO - order
default:
//unknown type
break;
}
return $value;
}
/**
* Auto-render Form Element
* @param string $key
* @param mixed $value
* @param array $attributes field attributes including render parameters, element options - see e_admin_ui::$fields for required format
* @return string
*/
function renderElement($key, $value, $attributes)
{
$parms = vartrue($attributes['writeParms'], array());
if(is_string($parms)) parse_str($parms, $parms);
switch($attributes['type'])
{
case 'number':
$maxlength = vartrue($parms['maxlength'], 255);
unset($parms['maxlength']);
if(!vartrue($parms['size'])) $parms['size'] = 15;
if(!vartrue($parms['class'])) $parms['class'] = 'tbox number';
return vartrue($parms['pre']).$this->text($key, $value, $maxlength, $parms).vartrue($parms['post']);
break;
case 'ip':
return $this->text($key, e107::getInstance()->ipDecode($value), 32, $parms);
break;
case 'url':
case 'text':
$maxlength = vartrue($parms['maxlength'], 255);
unset($parms['maxlength']);
return vartrue($parms['pre']).$this->text($key, $value, $maxlength, vartrue($parms['__options'])).vartrue($parms['post']);
break;
case 'textarea':
return $this->textarea($key, $value, vartrue($parms['rows'], 5), vartrue($parms['cols'], 40), vartrue($parms['__options']), vartrue($parms['counter'], false));
break;
case 'bbarea':
return $this->bbarea($key, $value, vartrue($parms['help']), vartrue($parms['helptag']), vartrue($parms['size'], 'medium'), vartrue($parms['counter'], false));
break;
case 'image': //TODO - thumb, image list shortcode, js tooltip...
$label = varset($parms['label'], 'LAN_EDIT');
unset($parms['label']);
return $this->imagepicker($key, $value, defset($label, $label), vartrue($parms['__options']));
break;
case 'icon':
$label = varset($parms['label'], 'LAN_EDIT');
$ajax = varset($parms['ajax'], true) ? true : false;
unset($parms['label'], $parms['ajax']);
return $this->iconpicker($key, $value, defset($label, $label), $parms, $ajax);
break;
case 'datestamp':
return $this->datepicker($key, $value, $parms);
break;
case 'dropdown':
$eloptions = vartrue($parms['__options'], array());
if(is_string($eloptions)) parse_str($eloptions);
unset($parms['dropdown']);
return $this->selectbox($name, $parms, $value, $eloptions);
break;
case 'userclass':
case 'userclasses':
$uc_options = vartrue($parms['classlist'], 'public,guest,nobody,member,classes,admin,main'); // defaults to 'public,guest,nobody,member,classes' (userclass handler)
unset($parms['classlist']);
$method = $attributes['type'] == 'userclass' ? 'uc_select' : 'uc_checkbox';
return $this->$method($key, $value, $uc_options, vartrue($parms['__options'], array()));
break;
/*case 'user_name':
case 'user_loginname':
case 'user_login':
case 'user_customtitle':
case 'user_email':*/
case 'user':
//user_id expected
// Just temporary solution, could be changed soon
if(!isset($parms['__options'])) $parms['__options'] = array();
if(!is_array($parms['__options'])) parse_str($parms['__options'], $parms['__options']);
if((empty($value) && vartrue($parms['currentInit'])) || vartrue($parms['current']))
{
$value = USERID;
if(vartrue($parms['current']))
{
$parms['__options']['readonly'] = true;
}
}
if(!is_array($value))
{
$value = get_user_data($value);
}
$colname = vartrue($parms['nameType'], 'user_name');
$parms['__options']['name'] = $colname;
if(!$value) $value = array();
$uname = varset($value[$colname]);
$value = varset($value['user_id'], 0);
return $this->userpicker(vartrue($parms['nameField'], $key.'_usersearch'), $key, $uname, $value, vartrue($parms['__options']));
break;
case 'boolean':
$lenabled = vartrue($parms['enabled'], 'LAN_ENABLED');
$ldisabled = vartrue($parms['disabled'], 'LAN_DISABLED');
unset($parms['enabled'], $parms['disabled']);
return $this->radio_switch($key, $value, defset($lenabled, $lenabled), defset($ldisabled, $ldisabled));
break;
case 'method': // Custom Function
return call_user_func_array(array($this, $key), array($value, 'write', $parms));
break;
default:
return $value;
break;
}
}
/**
* Generic List Form, used internal by admin UI
* Expected options array format:
*
* 'myplugin', // unique string used for building element ids, REQUIRED
* 'pid' => 'primary_id', // primary field name, REQUIRED
* 'url' => '{e_PLUGIN}myplug/admin_config.php', // if not set, e_SELF is used
* 'query' => 'mode=main&action=list', // or e_QUERY if not set
* 'head_query' => 'mode=main&action=list', // without field, asc and from vars, REQUIRED
* 'np_query' => 'mode=main&action=list', // without from var, REQUIRED for next/prev functionality
* 'legend' => 'Fieldset Legend', // hidden by default
* 'form_pre' => '', // markup to be added before opening form element (e.g. Filter form)
* 'form_post' => '', // markup to be added after closing form element
* 'fields' => array(...), // see e_admin_ui::$fields
* 'fieldpref' => array(...), // see e_admin_ui::$fieldpref
* 'table_pre' => '', // markup to be added before opening table element
* 'table_post' => '', // markup to be added after closing table element (e.g. Batch actions)
* 'fieldset_pre' => '', // markup to be added before opening fieldset element
* 'fieldset_post' => '', // markup to be added after closing fieldset element
* 'perPage' => 15, // if 0 - no next/prev navigation
* 'from' => 0, // current page, default 0
* 'field' => 'field_name', //current order field name, default - primary field
* 'asc' => 'desc', //current 'order by' rule, default 'asc'
* );
* $list = new e_admin_tree_model($data);
*
* TODO - move fieldset & table generation in separate methods, needed for ajax calls
* @param array $options
* @param e_admin_tree_model $list
* @param boolean $nocontainer don't enclose form in div container
* @return string
*/
public function listForm($options, $list, $nocontainer = false)
{
$tp = e107::getParser();
$tree = $list->getTree();
$total = $list->getTotal();
$amount = $options['perPage'];
$from = vartrue($options['from'], 0);
$field = vartrue($options['field'], $options['pid']);
$asc = strtoupper(vartrue($options['asc'], 'asc'));
$elid = $options['id'];
$query = isset($options['query']) ? $options['query'] : e_QUERY ;
$url = (isset($options['url']) ? $tp->replaceConstants($options['url'], 'abs') : e_SELF);
$formurl = $url.($query ? '?'.$query : '');
$fields = $options['fields'];
$current_fields = varset($options['fieldpref']) ? $options['fieldpref'] : array_keys($options['fields']);
$text = "
";
if(!$nocontainer)
{
$text = '
'.$text.'
';
}
return (vartrue($options['form_pre']).$text.vartrue($options['form_post']));
}
/**
* Generic DB Record Management Form.
* TODO - lans
* TODO - move fieldset & table generation in separate methods, needed for ajax calls
* Expected arrays format:
*
* 'myplugin',
* 'url' => '{e_PLUGIN}myplug/admin_config.php', //if not set, e_SELF is used
* 'query' => 'mode=main&action=edit&id=1', //or e_QUERY if not set
* 'tabs' => true, // TODO - NOT IMPLEMENTED YET - enable tabs (only if fieldset count is > 1)
* 'fieldsets' => array(
* 'general' => array(
* 'legend' => 'Fieldset Legend',
* 'fields' => array(...), //see e_admin_ui::$fields
* 'after_submit_options' => array('action' => 'Label'[,...]), // or true for default redirect options
* 'after_submit_default' => 'action_name',
* 'triggers' => 'auto', // standard create/update-cancel triggers
* //or custom trigger array in format array('sibmit' => array('Title', 'create', '1'), 'cancel') - trigger name - title, action, optional hidden value (in this case named sibmit_value)
* ),
*
* 'advanced' => array(
* 'legend' => 'Fieldset Legend',
* 'fields' => array(...), //see e_admin_ui::$fields
* 'after_submit_options' => array('__default' => 'action_name' 'action' => 'Label'[,...]), // or true for default redirect options
* 'triggers' => 'auto', // standard create/update-cancel triggers
* //or custom trigger array in format array('submit' => array('Title', 'create', '1'), 'cancel' => array('cancel', 'cancel')) - trigger name - title, action, optional hidden value (in this case named sibmit_value)
* )
* )
* );
* $models[0] = new e_admin_model($data);
* $models[0]->setFieldIdName('primary_id'); // you need to do it if you don't use your own admin model extension
*
* @param array $forms numerical array
* @param array $models numerical array with values instance of e_admin_model
* @param boolean $nocontainer don't enclose in div container
* @return string
*/
function createForm($forms, $models, $nocontainer = false)
{
$text = '';
foreach ($forms as $fid => $form)
{
$model = $models[$fid];
$query = isset($form['query']) ? $form['query'] : e_QUERY ;
$url = (isset($form['url']) ? e107::getParser()->replaceConstants($form['url'], 'abs') : e_SELF).($query ? '?'.$query : '');
$text .= "
";
e107::getJs()->footerInline("Form.focusFirstElement('{$form['id']}-form');");
}
if(!$nocontainer)
{
$text = '
'.$text.'
';
}
return $text;
}
// The 2 functions below are for demonstration purposes only, and may be moved/modified before release.
function filterType($fieldarray)
{
return " frm-> filterType() is Deprecated ";
}
function filterValue($type = '', $fields = '')
{
return " frm-> filterValue() is Deprecated. ";
}
/**
* Generates a batch options select component
* This component is generally associated with a table of items where one or more rows in the table can be selected (using checkboxes).
* The list options determine some processing that wil lbe applied to all checked rows when the form is submitted.
*
* @param array $options associative array of option elements, keyed on the option value
* @param array ucOptions [optional] associative array of userclass option groups to display, keyed on the option value prefix
* @return string the HTML for the form component
*/
function batchoptions($options, $ucOptions = null)
{
$text = "