(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 .= "
';
}
break;
case 'icon':
$value = '';
break;
case 'image': //TODO - thumb, js tooltip...
if($value)
{
$src = $tp->replaceConstants(vartrue($parms['pre']).$value, 'abs');
$alt = $src; //basename($value);
$ttl = vartrue($parms['thumb']) ? '' : vartrue($parms['title'], 'LAN_PREVIEW');
$value = ''.defset($ttl, $ttl).'';
}
break;
case 'datestamp':
$value = $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
$id = 0;
$ttl = '';
if(vartrue($parms['link']))
{
$id = vartrue($parms['__idval']);
if($value && !is_numeric($value))
{
$id = vartrue($parms['__idval']);
$ttl = $value;
}
elseif($value && is_numeric($value))
{
$id = $value;
$ttl = vartrue($parms['__nameval']);
}
}
if($id && $ttl && is_numeric($id))
{
$value = ''.$ttl.'';
}
else
{
$value = $ttl;
}
break;
case 'boolean':
$value = $value ? ADMIN_TRUE_ICON : ADMIN_FALSE_ICON;
break;
case 'url':
if(!$value) break;
$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;
case 'hidden':
return (vartrue($parms['show']) ? ($value ? $value : vartrue($parms['empty'])) : '');
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());
$tp = e107::getParser();
if(is_string($parms)) parse_str($parms, $parms);
if(vartrue($attributes['readonly'])) // quick fix (maybe 'noedit'=>'readonly'?)
{
return $this->renderValue($key, $value, $attributes);
}
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']), varset($parms['counter'], false));
break;
case 'bbarea':
return $this->bbarea($key, $value, vartrue($parms['help']), vartrue($parms['helptag']), vartrue($parms['size'], 'medium'), varset($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 'layouts': //to do - exclude param (exact match)
$location = varset($parms['plugin']); // empty - core
$ilocation = vartrue($parms['id'], $location); // omit if same as plugin name
$where = vartrue($parms['area'], 'front'); //default is 'front'
$filter = varset($parms['filter']);
$layouts = e107::getLayouts($location, $ilocation, $where, $filter);
if(varset($parms['default']))
{
$layouts = array('default' => $parms['default']) + $layouts;
}
return (vartrue($parms['raw']) ? $layouts : $this->selectbox($key, $layouts, $value));
break;
case 'templates': //to do - exclude param (exact match)
$templates = array();
if(varset($parms['default']))
{
$templates['default'] = defset($parms['default'], $parms['default']);
}
$location = vartrue($parms['plugin']) ? e_PLUGIN.$parms['plugin'].'/' : e_THEME;
$ilocation = vartrue($parms['location']);
$tmp = e107::getFile()->get_files($location.'templates/'.$ilocation, vartrue($parms['fmask'], '_template\.php$'), vartrue($parms['omit'], 'standard'), vartrue($parms['recurse_level'], 0));
foreach($tmp as $files)
{
$k = str_replace('_template.php', '', $files['fname']);
$templates[$k] = implode(' ', array_map('ucfirst', explode('_', $k))); //TODO add LANS?
}
// override
$where = vartrue($parms['area'], 'front');
$location = vartrue($parms['plugin']) ? $parms['plugin'].'/' : '';
$tmp = e107::getFile()->get_files(e107::getThemeInfo($where, 'rel').'templates/'.$location.$ilocation, vartrue($parms['fmask']), vartrue($parms['omit'], 'standard'), vartrue($parms['recurse_level'], 0));
foreach($tmp as $files)
{
$k = str_replace('_template.php', '', $files['fname']);
$templates[$k] = implode(' ', array_map('ucfirst', explode('_', $k))); //TODO add LANS?
}
return (vartrue($parms['raw']) ? $templates : $this->selectbox($key, $templates, $value));
break;
case 'dropdown':
$eloptions = vartrue($parms['__options'], array());
if(is_string($eloptions)) parse_str($eloptions);
unset($parms['__options']);
return $this->selectbox($key, $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;
case 'upload': //TODO - from method
return $tp->parseTemplate("{UPLOADFILE=".e_UPLOAD."}");
break;
case 'hidden':
$ret = (vartrue($parms['show']) ? ($value ? $value : vartrue($parms['empty'])) : '');
return $ret.$this->hidden($key, $value);
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'
* );
* $tree_models['myplugin'] = new e_admin_tree_model($data);
*
* TODO - move fieldset & table generation in separate methods, needed for ajax calls
* @param array $form_options
* @param e_admin_tree_model $tree_model
* @param boolean $nocontainer don't enclose form in div container
* @return string
*/
public function renderListForm($form_options, $tree_models, $nocontainer = false)
{
$tp = e107::getParser();
foreach ($form_options as $fid => $options)
{
$tree_model = $tree_models[$fid];
$tree = $tree_model->getTree();
$total = $tree_model->getTotal();
$amount = $options['perPage'];
$from = vartrue($options['from'], 0);
$field = vartrue($options['field'], $options['pid']);
$asc = strtoupper(vartrue($options['asc'], 'asc'));
$elid = $fid;//$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 renderCreateForm($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;
}
function renderCreateFieldset($id, $fdata, $model, $nocontainer = false)
{
$text = vartrue($fdata['fieldset_pre'])."
".vartrue($fdata['fieldset_post'])."
";
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 = "