Файл: library/XenForo/Template/Helper/Admin.php
Строк: 1958
<?php
//TODO: Document control options for each control
/**
* Helper methods for the admin template functions/tags.
*
* @package XenForo_Template
*/
class XenForo_Template_Helper_Admin
{
/**
* Internal counter used for uniquely ID'ing controls.
*
* @var integer
*/
protected static $_controlCounter = 1;
protected static $_controlIdLog = array();
/**
* Stores a single use ID for output. Useful for generating it in one function
* and defering to another (possibly recursive function) to use it.
*
* Null means it has not been set.
*
* @var null|string
*/
protected static $_oneUseId = null;
/**
* Internal counter for uniquely ID'ing list row popup groups.
*
* @var integer
*/
protected static $_listItemGroupCounter = 1;
/**
* Private constructor. Don't instantiate this object. Use it statically.
*/
private function __construct()
{
}
/**
* Gets a unique ID for the control
*
* @param string $name Name of the control. Will be used to generate the ID if possible and not overridden.
* @param array $rowOptions Collection of control options. Uses the id from this, if set.
*
* @return string
*/
protected static function _getControlId($name, array $controlOptions = null)
{
if (is_array($controlOptions) && isset($controlOptions['id']))
{
return $controlOptions['id'];
}
if ($name != '')
{
$name = preg_replace('/[^a-z0-9_-]/i', '', $name);
if (!isset(self::$_controlIdLog[$name]))
{
self::$_controlIdLog[$name] = 0;
}
$counter = self::$_controlIdLog[$name]++;
return 'ctrl_' . $name . ($counter ? "_$counter" : '');
}
return 'ctrl_' . self::$_controlCounter++;
}
/**
* Resets the control counter. This may cause duplicate IDs. Primarily used for testing.
*/
public static function resetControlCounter()
{
self::$_controlCounter = 1;
self::$_controlIdLog = array();
self::$_listItemGroupCounter = 1;
}
/**
* Array merging function to merge option and options tags. "Simple" form (value => label)
* data will be translated into a simple array format to be unambiguous.
*
* @param array $start The base array
* @param array $additional The data to add to the base array. Ignored if not an array.
* @param boolean $raw If true, escaping is not done on printable components
*
* @return array
*/
public static function mergeOptionArrays($start, $additional, $raw = false)
{
if (!is_array($start))
{
$start = array();
}
if (!is_array($additional))
{
return $start;
}
foreach ($additional AS $value => $label)
{
if (!is_array($label))
{
// turn value => label into basic array
$start[] = array('value' => $value, 'label' => $raw ? $label : htmlspecialchars($label));
}
else if (is_string($value))
{
// array format with string key -- opt group
$start[$raw ? $value : htmlspecialchars($value)] = $label;
}
else
{
// already array format
if (!$raw && !empty($label['label']))
{
$label['label'] = htmlspecialchars($label['label']);
}
$start[] = $label;
}
}
return $start;
}
/**
* Helper to quickly append classes to a list that may or not may exist.
* List must be within an array.
*
* @param array $array Array that contains the list
* @param string $key Key of the list
* @param string $append Classes to appended. Separate with spaces.
*
* @return array Original array, updated
*/
protected static function _appendClasses(array $array, $key, $append)
{
if (!empty($array[$key]))
{
$array[$key] .= ' ' . $append;
}
else
{
$array[$key] = $append;
}
return $array;
}
/**
* Gets the data-* attributes for a tag AS a string, from the list of options.
* The given array should be all options, not just the data array.
*
* @param array $options All options, possibly including a _data key.
*
* @return string Attributes AS string, with a leading space if there are attributes
*/
protected static function _getDataAttributesAsString(array $options)
{
if (empty($options['_data']) || !is_array($options['_data']))
{
return '';
}
$output = '';
foreach ($options['_data'] AS $key => $value)
{
$output .= ' data-' . $key . '="' . $value . '"';
}
return $output;
}
/**
* Outputs an HTML form.
*
* @param string $childElements Child elements
* @param array $options
*
* @return string
*/
public static function form($childElements, array $options)
{
$enctype = (!empty($options['upload']) ? ' enctype="multipart/form-data"' : '');
unset($options['upload']);
if (!isset($options['method']))
{
$options['method'] = 'post';
}
if (!isset($options['class']))
{
$options['class'] = 'xenForm formOverlay';
}
else if (strpos(" $options[class] ", ' xenForm ') === false)
{
$options['class'] = 'xenForm formOverlay ' . $options['class'];
}
if (strtolower($options['method']) == 'get' && ($questPos = strpos($options['action'], '?')) !== false)
{
$converted = XenForo_Template_Helper_Core::convertUrlToActionAndNamedParams($options['action']);
$options['action'] = $converted['action'];
$formHiddenElements = XenForo_Template_Helper_Core::getHiddenInputs($converted['params']);
}
else
{
$formHiddenElements = '';
}
if (strtolower($options['method']) == 'get')
{
$hiddenToken = '';
}
else
{
$visitor = XenForo_Visitor::getInstance();
$hiddenToken = '<input type="hidden" name="_xfToken" value="' . $visitor['csrf_token_page'] . '" />' . "n";
}
$attributes = '';
foreach ($options AS $name => $value)
{
$attributes .= " $name="$value"";
}
return '
<form' . $attributes . $enctype . '>' . $childElements . $formHiddenElements . $hiddenToken . '</form>
';
}
/**
* Wraps the specified control/inner text in a full unit.
*
* @param string Row label
* @param string Text of the control
* @param string Unique ID for the control
* @param array Standard row options:
* * hint - hint text shown under leabel
* * class - class to apply to whole unit
* * explain - text to show under control
* * labelHidden - boolean, if true label is not shown
* * html - arbitrary html to add between control and explain text
*
* @return string Control wrapped in label/row markup
*/
protected static function _wrapControlUnit($label, $controlText, $id, array $rowOptions)
{
$hint = (!empty($rowOptions['hint']) ? ' <dfn>' . $rowOptions['hint'] . '</dfn>' : '');
$class = (!empty($rowOptions['class']) ? " $rowOptions[class]" : '');
$explain = (!empty($rowOptions['explain']) ? "n" . '<p class="explain">' . $rowOptions['explain'] . '</p>' : '');
$labelClass = (!empty($rowOptions['labelHidden']) ? ' surplusLabel' : '');
$dataAttributes = self::_getDataAttributesAsString($rowOptions);
if ($id)
{
$label = '<label for="' . $id . '">' . $label . '</label>';
}
return '
<dl class="ctrlUnit' . $labelClass . $class . '"' . $dataAttributes . '>
<dt>' . $label . $hint . '</dt>
<dd>
' . $controlText . (isset($rowOptions['html']) ? "n$rowOptions[html]" : '') . $explain . '
</dd>
</dl>
';
}
/**
* Outputs a control unit row. This does not contain any input field unless you manually
* include one. Note that the label will not be "for" any input.
*
* @param string $label Label text
* @param array $rowOptions Collection of options that relate to the row
*
* @return string
*/
public static function controlUnit($label, array $rowOptions = array())
{
return self::_wrapControlUnit($label, '', '', $rowOptions);
}
/**
* Outputs a submit unit row containing submit or reset buttons (and any additional HTML).
*
* @param string $childText Output from text that was within the submitunit tag
* @param array $controlOptions Options for this control
*
* @return string
*/
public static function submitUnit($childText, array $controlOptions = array())
{
if (!empty($controlOptions['save']))
{
$saveKey = (!empty($controlOptions['savekey']) ? $controlOptions['savekey'] : 's');
$name = (!empty($controlOptions['name']) ? ' name="' . $controlOptions['name'] . '"' : '');
$saveClass = (!empty($controlOptions['saveclass']) ? " $controlOptions[saveclass]" : '');
$prepend = "n" . '<input type="submit"' . $name . ' value="' . $controlOptions['save'] . '" class="button primary' . $saveClass . '" accesskey="' . $saveKey . '" />';
}
else
{
$prepend = '';
}
if (!empty($controlOptions['reset']))
{
$resetKey = (!empty($controlOptions['resetkey']) ? $controlOptions['resetkey'] : 'r');
$resetClass = (!empty($controlOptions['resetclass']) ? " $controlOptions[resetclass]" : '');
$append = '<input type="reset" value="' . $controlOptions['reset'] . '" class="button' . $resetClass . '" accesskey="' . $resetKey . '" />' . "n";
}
else
{
$append = '';
}
$explain = (!empty($controlOptions['explain']) ? "n" . '<p class="explain">' . $controlOptions['explain'] . '</p>' : '');
if ($explain)
{
$append .= $explain;
}
if ($childText === '')
{
$childText = "n";
}
return '<dl class="ctrlUnit submitUnit"><dt></dt><dd>' . $prepend . $childText . $append . '</dd></dl>';
}
/**
* Gets a text, password, search, number (etc) text-type input.
* Standard text inputs may span multiple rows, turning into a textarea.
*
* @param string $type Type of input requested; either text or password
* @param string $name Name of the input field. Already HTML escaped.
* @param string $value Default value for the input field. Already HTML escaped.
* @param array $controlOptions Array of options for the control
* @param string $id Optional ID for the input. If not specified, one will be generated.
*
* @return string
*/
protected static function _getTextInput($type, $name, $value, array $controlOptions, $id = '')
{
if ($id === '')
{
$id = self::_getControlId($name, $controlOptions);
}
$type = htmlspecialchars($type);
$title = (!empty($controlOptions['title']) ? ' title="' . $controlOptions['title'] . '"' : '');
$placeholder = (!empty($controlOptions['placeholder']) ? ' placeholder="' . $controlOptions['placeholder'] . '"' : '');
$autofocus = (!empty($controlOptions['autofocus']) ? ' autofocus="autofocus"' : '');
$autocomplete = (!empty($controlOptions['autocomplete']) ? ' autocomplete="' . $controlOptions['autocomplete'] . '"' : '');
$size = (!empty($controlOptions['size']) ? ' size="' . $controlOptions['size'] . '"' : '');
$maxlength = (!empty($controlOptions['maxlength']) ? ' maxlength="' . $controlOptions['maxlength'] . '"' : '');
$readonly = (!empty($controlOptions['readonly']) ? ' readonly="readonly"' : '');
// input:number spinbox type
$step = (($type == 'number' && isset($controlOptions['step'])) ? ' step="' . $controlOptions['step'] . '"' : '');
$min = (($type == 'number' && isset($controlOptions['min'])) ? ' min="' . $controlOptions['min'] . '"' : '');
$max = (($type == 'number' && isset($controlOptions['max'])) ? ' max="' . $controlOptions['max'] . '"' : '');
// input:search type
if ($type == 'search')
{
$results = ' results="' . (!empty($controlOptions['results']) ? intval($controlOptions['results']) : 0) . '"';
}
else
{
$results = '';
}
if (!empty($controlOptions['code']))
{
// add code class for this, add wrap for text areas below
$controlOptions = self::_appendClasses($controlOptions, 'inputclass', 'code');
if (empty($controlOptions['dir']))
{
$controlOptions['dir'] = 'ltr';
}
}
$inputClass = (!empty($controlOptions['inputclass']) ? ' ' . $controlOptions['inputclass'] : '');
$dir = (!empty($controlOptions['dir']) ? ' dir="' . $controlOptions['dir'] . '"' : '');
$dataAttributes = self::_getDataAttributesAsString($controlOptions);
$after = (!empty($controlOptions['after']) ? $controlOptions['after'] : '');
if (!empty($controlOptions['rows']) && $type == 'text')
{
$cols = (!empty($controlOptions['size']) ? $controlOptions['size'] : 60);
$wrap = (!empty($controlOptions['code']) ? ' wrap="off"' : '');
return "<textarea name="{$name}" rows="{$controlOptions['rows']}" cols="{$cols}"{$title}{$placeholder}{$autofocus}{$readonly}{$wrap}{$dir} class="textCtrl{$inputClass}"{$dataAttributes} id="{$id}">{$value}</textarea>$after";
}
else
{
return "<input type="{$type}" name="{$name}" value="{$value}"{$size}{$maxlength}{$title}{$placeholder}{$autofocus}{$autocomplete}{$readonly}{$dir}{$step}{$min}{$max}{$results} class="textCtrl{$inputClass}"{$dataAttributes} id="{$id}" />$after";
}
}
/**
* Helper to prepare and return the HTML for a control unit with a single text box.
*
* @param string Label for the row
* @param string Name of the text box
* @param string Default value of the text box
* @param array Options that relate to the row
* @param array Options that relate to the control
*
* @return string
*/
public static function textBoxUnit($label, $name, $value, array $rowOptions = array(), array $controlOptions = array())
{
$id = self::_getControlId($name, $controlOptions);
$type = (!empty($controlOptions['type']) ? $controlOptions['type'] : 'text');
$input = self::_getTextInput($type, $name, $value, $controlOptions, $id);
return self::_wrapControlUnit($label, $input, $id, $rowOptions);
}
/**
* Helper to prepare and return the HTML for a single text box.
*
* @param string Name of the text box
* @param string Default value of the text box
* @param array Options that relate to the control
*
* @return string
*/
public static function textBox($name, $value, array $controlOptions = array())
{
$type = (!empty($controlOptions['type']) ? $controlOptions['type'] : 'text');
return self::_getTextInput($type, $name, $value, $controlOptions);
}
/**
* Helper to prepare and return the HTML for a control unit with a single password input.
*
* @param string Label for the row
* @param string Name of the text box
* @param string Default value of the text box
* @param array Options that relate to the row
* @param array Options that relate to the control
*
* @return string
*/
public static function passwordUnit($label, $name, $value, array $rowOptions = array(), array $controlOptions = array())
{
$id = self::_getControlId($name, $controlOptions);
$input = self::_getTextInput('password', $name, $value, $controlOptions, $id);
return self::_wrapControlUnit($label, $input, $id, $rowOptions);
}
/**
* Helper to prepare and return the HTML for a single password input.
*
* @param string Name of the text box
* @param string Default value of the text box
* @param array Options that relate to the control
*
* @return string
*/
public static function password($name, $value, array $controlOptions = array())
{
return self::_getTextInput('password', $name, $value, $controlOptions);
}
/**
* Helper to prepare and return the HTML for a control unit with a single file upload input.
*
* @param string Label for the row
* @param string Name of the input
* @param string Default value of the upload box (likely ignored by browsers)
* @param array Options that relate to the row
* @param array Options that relate to the control
*
* @return string
*/
public static function uploadUnit($label, $name, $value, array $rowOptions = array(), array $controlOptions = array())
{
$id = self::_getControlId($name, $controlOptions);
$input = self::_getUploadInput($name, $value, $controlOptions, $id);
return self::_wrapControlUnit($label, $input, $id, $rowOptions);
}
/**
* Helper to prepare and return the HTML for a single file upload input.
*
* @param string Name of the input
* @param string Default value of the text box (likely ignored)
* @param array Options that relate to the control
*
* @return string
*/
public static function upload($name, $value, array $controlOptions = array())
{
return self::_getUploadInput($name, $value, $controlOptions);
}
/**
* Gets a upload input.
*
* @param string $name Name of the input
* @param string $value Default selected option
* @param array $controlOptions Control options
* @param string $id Optional ID for the input. If not specified, one will be generated.
*
* @return string
*/
protected static function _getUploadInput($name, $value, array $controlOptions, $id = '')
{
$inputClass = (!empty($controlOptions['inputclass']) ? ' class="' . $controlOptions['inputclass'] . '"' : '');
$dataAttributes = self::_getDataAttributesAsString($controlOptions);
return "<input type="file" name="{$name}" value="{$value}"{$inputClass}{$dataAttributes} id="{$id}" />";
}
/**
* Helper to prepare and return the HTML for a control unit with a single spin box input.
*
* @param string Label for the row
* @param string Name of the text box
* @param string Default value of the text box
* @param array Options that relate to the row
* @param array Options that relate to the control
*
* @return string
*/
public static function spinBoxUnit($label, $name, $value, array $rowOptions = array(), array $controlOptions = array())
{
$id = self::_getControlId($name, $controlOptions);
$input = self::_getSpinBoxInput($name, $value, $controlOptions, $id);
return self::_wrapControlUnit($label, $input, $id, $rowOptions);
}
/**
* Helper to prepare and return the HTML for a control unit with a single spin box input.
*
* @param string Name of the text box
* @param string Default value of the text box
* @param array Options that relate to the control
*
* @return string
*/
public static function spinBox($name, $value, array $controlOptions = array())
{
return self::_getSpinBoxInput($name, $value, $controlOptions);
}
/**
* Gets a spin box input.
*
* @param string $name Name of the input
* @param string $value Default selected option
* @param array $controlOptions Control options
* @param string $id Optional ID for the input. If not specified, one will be generated.
*
* @return string
*/
protected static function _getSpinBoxInput($name, $value, array $controlOptions, $id = '')
{
$value = floatval($value);
if (!empty($controlOptions['step']))
{
$controlOptions['step'] = floatval($controlOptions['step']);
}
else
{
$controlOptions['step'] = 1;
}
if (isset($controlOptions['min']) && $controlOptions['min'] !== '')
{
$controlOptions['min'] = floatval($controlOptions['min']);
}
if (isset($controlOptions['max']) && $controlOptions['max'] !== '')
{
$controlOptions['max'] = floatval($controlOptions['max']);
}
$controlOptions = self::_appendClasses($controlOptions, 'inputclass', 'number SpinBox');
return self::_getTextInput('number', $name, $value, $controlOptions, $id);
}
/**
* Helper to prepare and return the HTML for a control unit with a combo box input.
*
* @param string $label Label for the unit
* @param string $name Name of the text box
* @param string $value Default value for the text box
* @param array $choices Choices for the select
* @param array $rowOptions Options that relate to the whole row
* @param array $controlOptions Options that relate to the text/select controls
*
* @return string
*/
public static function comboBoxUnit($label, $name, $value, array $choices, array $rowOptions = array(), array $controlOptions = array())
{
$id = self::_getControlId($name, $controlOptions);
$input = self::_getComboBoxInput($name, $value, $choices, $controlOptions, $id);
return self::_wrapControlUnit($label, $input, $id, $rowOptions);
}
/**
* Helper to prepare and return the HTML for a control unit with a combo box input.
*
* @param string $name Name of the text box
* @param string $value Default value for the text box
* @param array $choices Choices for the select
* @param array $controlOptions Options that relate to the text/select controls
*
* @return string
*/
public static function comboBox($name, $value, array $choices, array $controlOptions = array())
{
return self::_getComboBoxInput($name, $value, $choices, $controlOptions);
}
/**
* Gets a combo box input.
*
* @param string $name Name of the select input. If multiple selections are allow, [] will be appended.
* @param string $value Default selected option
* @param array $choices Choices for the select
* @param array $controlOptions Control options
* @param string $id Optional ID for the input. If not specified, one will be generated.
*
* @return string
*/
protected static function _getComboBoxInput($name, $value, array $choices, array $controlOptions, $id = '')
{
if ($id === '')
{
$id = self::_getControlId($name, $controlOptions);
}
$controlOptions = self::_appendClasses($controlOptions, 'inputclass', 'ComboBox');
$textInput = self::_getTextInput('text', $name, $value, $controlOptions, $id);
$choiceHtml = self::_processControlChoices(
$choices,
$value,
array(
'group' => array('self', '_getComboBoxGroupHtml'),
'option' => array('self', '_getComboBoxOptionHtml')
),
array('allowNestedGroups' => 1)
);
return $textInput . "n<select class="ComboBox">n$choiceHtml</select>";
}
/**
* Callback for generating combo box optgroup HTML.
*
* @param $label Label for the group
* @param $optionHtml HTML for the options within the group
*
* @return string
*/
protected static function _getComboBoxGroupHtml($label, $optionHtml)
{
return "<optgroup label="$label">n$optionHtml</optgroup>n";
}
/**
* Callback for generating combo box option HTML
*
* @param string $value Value for the option (what it submitted to the server)
* @param string $label Label for the option (printable)
*
* @return string
*/
protected static function _getComboBoxOptionHtml($value, $label)
{
return "<option>$label</option>n";
}
/**
* Helper to prepare and return the HTML for a control unit with a single select input.
*
* @param string $label Label for the unit
* @param string $name Name of the select
* @param string $value Selected value for the select
* @param array $choices Choices for the select
* @param array $rowOptions Options that relate to the whole row
* @param array $controlOptions Options that relate to the select control
*
* @return string
*/
public static function selectUnit($label, $name, $value, array $choices, array $rowOptions = array(), array $controlOptions = array())
{
$id = self::_getControlId($name, $controlOptions);
$input = self::_getSelectInput($name, $value, $choices, $controlOptions, $id);
return self::_wrapControlUnit($label, $input, $id, $rowOptions);
}
/**
* Helper to prepare and return the HTML for a single select input.
*
* @param string $name Name of the select
* @param string $value Selected value for the select
* @param array $choices Choices for the select
* @param array $controlOptions Options that relate to the select control
*
* @return string
*/
public static function select($name, $value, array $choices, array $controlOptions = array())
{
return self::_getSelectInput($name, $value, $choices, $controlOptions);
}
/**
* Gets a select input.
*
* @param string $name Name of the select input. If multiple selections are allow, [] will be appended.
* @param string $value Default selected option
* @param array $choices Choices for the select
* @param array $controlOptions Control options
* @param string $id Optional ID for the input. If not specified, one will be generated.
*
* @return string
*/
protected static function _getSelectInput($name, $value, array $choices, array $controlOptions, $id = '')
{
if ($id === '')
{
$id = self::_getControlId($name, $controlOptions);
}
$choiceHtml = self::_processControlChoices(
$choices,
$value,
array(
'group' => array('self', '_getSelectGroupHtml'),
'option' => array('self', '_getSelectOptionHtml')
),
array('allowNestedGroups' => 1)
);
$multiple = (!empty($controlOptions['multiple']) ? ' multiple="multiple"' : '');
if ($multiple)
{
$name .= "[]";
}
if ($multiple && empty($controlOptions['size']))
{
$controlOptions['size'] = 5;
}
$title = (!empty($controlOptions['title']) ? ' title="' . $controlOptions['title'] . '"' : '');
$size = (!empty($controlOptions['size']) ? ' size="' . $controlOptions['size'] . '"' : '');
$inputClass = (!empty($controlOptions['inputclass']) ? " $controlOptions[inputclass]" : '');
$readonly = (!empty($controlOptions['readonly']) ? ' onclick="return false"' : '');
$dataAttributes = self::_getDataAttributesAsString($controlOptions);
return "<select name="$name"$title$size$multiple class="textCtrl$inputClass"$readonly$dataAttributes id="$id">n$choiceHtml</select>";
}
/**
* Callback for generating select optgroup HTML.
*
* @param $label Label for the group
* @param $optionHtml HTML for the options within the group
*
* @return string
*/
protected static function _getSelectGroupHtml($label, $optionHtml)
{
return "<optgroup label="$label">n$optionHtml</optgroup>n";
}
/**
* Callback for generating select option HTML
*
* @param string $value Value for the option (what it submitted to the server)
* @param string $label Label for the option (printable)
* @param boolean $selected Whether this option is selected
* @param array $extra Extra data about the option
*
* @return string
*/
protected static function _getSelectOptionHtml($value, $label, $selected, array $extra = array())
{
$selectedHtml = ($selected ? ' selected="selected"' : '');
$class = (isset($extra['class']) ? " class="$extra[class]"" : '');
$dataAttributes = self::_getDataAttributesAsString($extra);
if (!empty($extra['depth']))
{
$prefix = str_repeat(' ', $extra['depth']);
}
else
{
$prefix = '';
}
if (!empty($extra['disabled']) || !empty($extra['optdisabled']))
{
$disabledHtml = ' disabled="disabled"';
}
else
{
$disabledHtml = '';
}
$s = (string)$selected;
return "<option value="$value"$class$selectedHtml$disabledHtml$dataAttributes>$prefix$label</option>n";
}
/**
* Helper to prepare and return the HTML for a control unit with a collection of radio inputs.
*
* @param string $label Label for the unit
* @param string $name Name of the radios
* @param string $value Selected value for the radio
* @param array $choices Choices for the radios
* @param array $rowOptions Options that relate to the whole row
* @param array $controlOptions Options that relate to the radio controls
*
* @return string
*/
public static function radioUnit($label, $name, $value, array $choices, array $rowOptions = array(), array $controlOptions = array())
{
$input = self::_getRadioInput($name, $value, $choices, $controlOptions);
return self::_wrapControlUnit($label, $input, '', $rowOptions);
}
/**
* Helper to prepare and return the HTML for a collection of radio inputs.
*
* @param string $name Name of the radios
* @param string $value Selected value for the radio
* @param array $choices Choices for the radios
* @param array $controlOptions Options that relate to the radio controls
*
* @return string
*/
public static function radio($name, $value, array $choices, array $controlOptions = array())
{
return self::_getRadioInput($name, $value, $choices, $controlOptions);
}
/**
* Gets a collection of radio inputs.
*
* @param string $name Name of the radop inputs.
* @param string $value Default selected option
* @param array $choices Choices for the radios
* @param array $controlOptions Control options
*
* @return string
*/
protected static function _getRadioInput($name, $value, array $choices, array $controlOptions)
{
$options = array('defaultName' => $name);
if (!empty($controlOptions['title']))
{
$options['labelTitle'] = $controlOptions['title'];
}
if (!empty($controlOptions['inputclass']))
{
$options['inputclass'] = $controlOptions['inputclass'];
}
$options['readonly'] = !empty($controlOptions['readonly']);
$choiceHtml = self::_processControlChoices(
$choices,
$value,
array(
'group' => array('self', '_getRadioGroupHtml'),
'option' => array('self', '_getRadioOptionHtml')
),
$options
);
$dataAttributes = self::_getDataAttributesAsString($controlOptions);
$id = (!empty($controlOptions['id']) ? ' id="' . $controlOptions['id'] . '"' : '');
$listClass = (!empty($controlOptions['listclass']) ? ' class="' . $controlOptions['listclass'] . '"' : '');
return "<ul{$listClass}{$dataAttributes}{$id}>n$choiceHtml</ul>";
}
/**
* Callback for generating radio optgroup HTML. At this time, optgroups are ignored.
*
* @param $label Label for the group
* @param $optionHtml HTML for the options within the group
*
* @return string
*/
protected static function _getRadioGroupHtml($label, $optionHtml)
{
return $optionHtml;
}
/**
* Callback for generating radio option HTML.
*
* @param string $value Value for the option (what it submitted to the server)
* @param string $label Label for the option (printable)
* @param boolean $selected Whether this option is selected
* @param array $extra Extra data about the radio
* @param array $options Parsing options
*
* @return string
*/
protected static function _getRadioOptionHtml($value, $label, $selected, array $extra = array(), array $options = array())
{
$selectedHtml = ($selected ? ' checked="checked"' : '');
$name = (isset($options['defaultName']) ? $options['defaultName'] : '');
$hint = (isset($extra['hint']) ? ' <p class="hint">' . $extra['hint'] . '</p>' : '');
$id = self::_getControlId($name . '_' . $value);
$disablerHtml = self::_getDisablerHtml($extra, $id);
if (!empty($options['inputclass']))
{
$extra['inputclass'] = $options['inputclass'];
}
if (!empty($extra['inputclass']))
{
$inputClass = ' class="' . $extra['inputclass'] . ($disablerHtml ? ' Disabler' : '') . '"';
}
else
{
$inputClass = ($disablerHtml ? ' class="Disabler"' : '');
}
if (!empty($extra['depth']))
{
$prefix = str_repeat(' ', $extra['depth']);
}
else
{
$prefix = '';
}
if (!empty($extra['unselectable']))
{
$unselectable = ' disabled="disabled"';
$extra['class'] = (isset($extra['class']) ? "$extra[class] unselectable" : 'unselectable');
}
else
{
$unselectable = '';
}
$class = (isset($extra['class']) ? " class="$extra[class]"" : '');
$title = (isset($extra['title']) ? " title="$extra[title]"" : '');
$readonly = ((!empty($options['readonly']) || !empty($extra['readonly'])) ? ' onclick="return false"' : '');
$dataAttributes = self::_getDataAttributesAsString($extra);
return "<li><label for="$id"$class$title><input type="radio" name="$name" value="$value"$readonly$inputClass$unselectable id="$id"$selectedHtml$dataAttributes />"
. "$prefix $label</label>$hint$disablerHtml</li>n";
}
/**
* Helper to prepare and return the HTML for a control unit with a collection of check box inputs.
*
* @param string $label Label for the unit
* @param string $name Default name of the chec kbox. If used, [] will be appended.
* @param array $choices Choices for the check box
* @param array $rowOptions Options that relate to the whole row
* @param array $controlOptions Options that relate to the check box controls
*
* @return string
*/
public static function checkBoxUnit($label, $name, array $choices, array $rowOptions = array(), array $controlOptions = array())
{
$input = self::_getCheckBoxInput($name, $choices, $controlOptions);
return self::_wrapControlUnit($label, $input, '', $rowOptions);
}
/**
* Helper to prepare and return the HTML for a collection of check box inputs.
*
* @param string $name Default name of the chec kbox. If used, [] will be appended.
* @param array $choices Choices for the check box
* @param array $controlOptions Options that relate to the check box controls
*
* @return string
*/
public static function checkBox($name, array $choices, array $controlOptions = array())
{
return self::_getCheckBoxInput($name, $choices, $controlOptions);
}
/**
* Gets a collection of check box inputs.
*
* @param string $name Default name of the check box. If used, [] will be appended.
* @param array $choices Choices for the check box
* @param array $controlOptions Control options
*
* @return string
*/
protected static function _getCheckBoxInput($name, array $choices, array $controlOptions)
{
$options = array('defaultName' => $name);
if (!empty($controlOptions['title']))
{
$options['labelTitle'] = $controlOptions['title'];
}
if (!empty($controlOptions['inputclass']))
{
$options['inputclass'] = $controlOptions['inputclass'];
}
$choiceHtml = self::_processControlChoices(
$choices,
false,
array(
'group' => array('self', '_getCheckBoxGroupHtml'),
'option' => array('self', '_getCheckBoxOptionHtml')
),
$options
);
$dataAttributes = self::_getDataAttributesAsString($controlOptions);
$id = (!empty($controlOptions['id']) ? ' id="' . $controlOptions['id'] . '"' : '');
$listClass = (!empty($controlOptions['listclass']) ? ' class="' . $controlOptions['listclass'] . '"' : '');
return "<ul{$listClass}{$dataAttributes}{$id}>n$choiceHtml</ul>";
}
/**
* Callback for generating check box optgroup HTML. At this time, optgroups are ignored.
*
* @param $label Label for the group
* @param $optionHtml HTML for the options within the group
*
* @return string
*/
protected static function _getCheckBoxGroupHtml($label, $optionHtml)
{
return $optionHtml;
}
/**
* Callback for generating check box option HTML.
*
* @param string $value Value for the option (what it submitted to the server)
* @param string $label Label for the option (printable)
* @param boolean $selected Whether this option is selected
* @param array $extra Extra data about the check box
* @param array $options Parsing options
*
* @return string
*/
protected static function _getCheckBoxOptionHtml($value, $label, $selected, array $extra = array(), array $options = array())
{
$selectedHtml = ($selected ? ' checked="checked"' : '');
$hint = (isset($extra['hint']) ? ' <p class="hint">' . $extra['hint'] . '</p>' : '');
if (!empty($extra['name']))
{
if ($extra['name'] == '__NO_NAME__')
{
$name = '';
}
else if ($extra['name'][0] == '[' && isset($options['defaultName']))
{
$name = $options['defaultName'] . $extra['name'];
}
else
{
$name = $extra['name'];
}
}
else if (isset($options['defaultName']))
{
if (substr($options['defaultName'], -2) == '[]')
{
$name = $options['defaultName'];
}
else
{
$name = $options['defaultName'] . '[]';
}
}
else
{
$name = '';
}
if ($value === '')
{
$value = '1';
}
$id = (!empty($extra['id']) ? $extra['id'] : self::_getControlId($name . '_' . $value));
$disablerHtml = self::_getDisablerHtml($extra, $id);
if (!empty($options['inputclass']))
{
$extra['inputclass'] = $options['inputclass'];
}
if (!empty($extra['inputclass']))
{
$inputClass = ' class="' . $extra['inputclass'] . ($disablerHtml ? ' Disabler' : '') . '"';
}
else
{
$inputClass = ($disablerHtml ? ' class="Disabler"' : '');
}
if (!empty($extra['unselectable']))
{
$unselectable = ' disabled="disabled"';
$extra['class'] = (isset($extra['class']) ? "$extra[class] unselectable" : 'unselectable');
}
else
{
$unselectable = '';
}
$name = ($name !== '' ? " name="$name"" : '');
$class = (isset($extra['class']) ? " class="$extra[class]"" : '');
$title = (isset($extra['title']) ? " title="$extra[title]"" : '');
$readonly = ((!empty($options['readonly']) || !empty($extra['readonly'])) ? ' onclick="return false"' : '');
$dataAttributes = self::_getDataAttributesAsString($extra);
return "<li><label for="$id"$class$title><input type="checkbox"$name value="$value"$readonly$inputClass$unselectable id="$id"$selectedHtml$dataAttributes />"
. " $label</label>$hint$disablerHtml</li>n";
}
/**
* Gets the necessary HTML to make disabler controls (if dependent controls
* are specified).
*
* @param array $optionInfo Information about the option. Disablers searched for in "disabled" key.
* @param string $optionId ID that is being used for the parent of the disabler
*
* @return string HTML for the disabled controls, if applicable
*/
protected static function _getDisablerHtml(array $optionInfo, $optionId)
{
$disablerHtml = '';
if (!empty($optionInfo['disabled']) && is_array($optionInfo['disabled']))
{
$disablerHtml = "n<ul id="{$optionId}_Disabler" class="disablerList">";
foreach ($optionInfo['disabled'] AS $disabled)
{
$disablerHtml .= "n<li>$disabled</li>";
}
$disablerHtml .= "n</ul>n";
}
return $disablerHtml;
}
/**
* Processes the list of choices for a control into the appropriate HTML output.
*
* @param array $choices Array of choices
* @param string|array $selectedValue Selected value
* @param array $callbacks Callbacks. Define 2 keys: group and option
* @param array $options Extra options to manipulate the choices.
*
* @return string
*/
protected static function _processControlChoices(array $choices, $selectedValue, array $callbacks, array $options = array())
{
if (empty($choices))
{
return '';
}
$output = '';
$options = array_merge(array(
'allowNestedGroups' => 1000,
'defaultName' => ''
), $options);
$childOptions = $options;
$childOptions['allowNestedGroups']--;
foreach ($choices AS $label => $choice)
{
if ((is_string($label) && !isset($choice['label'])) || !is_array($choice) || !isset($choice['label']))
{
if (is_array($choice))
{
// opt group
$groupOptionHtml = self::_processControlChoices($choice, $selectedValue, $callbacks, $childOptions);
if ($groupOptionHtml)
{
if ($options['allowNestedGroups'] > 0)
{
$output .= call_user_func($callbacks['group'], $label, $groupOptionHtml, $options);
}
else
{
$output .= $groupOptionHtml;
}
}
}
else
{
// simple value => label construct
$value = $label;
$label = $choice;
if ($selectedValue !== null && $selectedValue !== false)
{
if (is_array($selectedValue))
{
$selected = in_array($value, $selectedValue);
}
else
{
$selected = (strval($selectedValue) == strval($value));
}
}
else
{
$selected = false;
}
$output .= call_user_func($callbacks['option'], $value, $label, $selected, array(), $options);
}
}
else
{
// advanced construct
if (!empty($choice['selected']))
{
$selected = (boolean)$choice['selected'];
}
else if ($selectedValue !== null && $selectedValue !== false && isset($choice['value']))
{
if (is_array($selectedValue))
{
$selected = in_array($choice['value'], $selectedValue);
}
else
{
$selected = (strval($selectedValue) == strval($choice['value']));
}
}
else
{
$selected = false;
}
$choice['value'] = (isset($choice['value']) ? $choice['value'] : '');
$output .= call_user_func($callbacks['option'], $choice['value'], $choice['label'], $selected, $choice, $options);
}
}
return $output;
}
/**
* Returns a list item element.
*
* @param array $controlOptions Options relating to the item
* @param array $popups A list of popups (HTML) that belong to the item
*
* @return string List row HTML
*/
public static function listItem(array $controlOptions, array $popups)
{
// active toggle handler
if (isset($controlOptions['toggle']))
{
if ($controlOptions['toggle'])
{
$toggleChecked = ' checked="checked"';
}
else
{
$toggleChecked = '';
XenForo_Template_Helper_Core::addClass('disabled', $controlOptions['labelclass']);
}
if (!empty($controlOptions['toggletitle']))
{
$toggleClass = ' Tooltip';
$toggleTitle = " title="$controlOptions[toggletitle]" data-tipclass="flipped" data-offsetx="2" data-offsety="-2"";
}
else
{
$toggleTitle = '';
}
$toggle = '
<input type="hidden" name="exists[' . $controlOptions['id'] . ']" value="1" />
<label class="toggler secondaryContent' . $toggleClass . '"' . $toggleTitle . '><input type="checkbox" name="id[' . $controlOptions['id'] . ']" value="1" ' . $toggleChecked . ' class="SubmitOnChange Toggler" /></label>';
}
else
{
$toggle = '';
}
if (!empty($controlOptions['selectable']))
{
$selectName = isset($controlOptions['selectname']) ? $controlOptions['selectname'] : '';
$selectValue = isset($controlOptions['selectvalue']) ? $controlOptions['selectvalue'] : $controlOptions['id'];
$selectDisabled = !empty($controlOptions['selectdisabled']) ? ' disabled="disabled"' : '';
if (!empty($controlOptions['selecttooltip']))
{
$selectTitle = ' title="' . $controlOptions['selecttooltip'] . '"';
$selectClass = ' Tooltip';
}
else
{
$selectTitle = '';
$selectClass = '';
}
$select = '<label class="secondaryContent selectListItem' . $selectClass . '"' . $selectTitle . '><input type="checkbox" name="' . $selectName . '" value="' . $selectValue . '" ' . (!empty($controlOptions['selected']) ? ' checked="checked"' : '') . $selectDisabled . ' /></label>';
}
else
{
$select = '';
}
if (!empty($controlOptions['tooltip']))
{
$tooltip = ' title="' . $controlOptions['tooltip'] . '" data-offsetx="10"';
XenForo_Template_Helper_Core::addClass('Tooltip', $controlOptions['linkclass']);
}
else
{
$tooltip = '';
}
$dataOptions = '';
foreach ($controlOptions AS $controlOptionId => $controlOptionValue)
{
if (substr($controlOptionId, 0, 5) == 'data-')
{
$dataOptions .= " $controlOptionId="$controlOptionValue"";
}
}
$extraClasses = (!empty($controlOptions['class']) ? ' ' . $controlOptions['class'] : '');
$labelClass = (!empty($controlOptions['labelclass']) ? ' class="' . $controlOptions['labelclass'] . '"' : '');
$linkClass = (!empty($controlOptions['linkclass']) ? ' class="' . $controlOptions['linkclass'] . '"' : '');
$href = (!empty($controlOptions['href']) ? $controlOptions['href'] : '');
$target = (!empty($controlOptions['target']) ? $controlOptions['target'] : '');
$linkStyle = (!empty($controlOptions['linkstyle']) ? ' style="' . $controlOptions['linkstyle'] . '"' : '');
$beforeLabel = (!empty($controlOptions['beforelabel']) ? $controlOptions['beforelabel'] : '');
if (empty($controlOptions['delete']))
{
$delete = '';
}
else
{
$deletePhrase = new XenForo_Phrase('delete') . '...';
$deleteHint = (!empty($controlOptions['deletehint']) ? $controlOptions['deletehint'] : $deletePhrase);
if ($controlOptions['delete'] === '#')
{
$delete = '<a class="delete secondaryContent"></a>' . "n";
}
else
{
$delete = '<a href="' . $controlOptions['delete'] . '" class="delete OverlayTrigger secondaryContent" title="' . $deleteHint . '"><span>' . $deletePhrase . '</span></a>' . "n";
}
}
$href = ($href ? ' href="' . $href . '"' : '');
$target = ($target ? ' target="' . $target . '"' : '');
$output = '
<li class="listItem primaryContent' . $extraClasses . '" id="' . self::getListItemId($controlOptions['id']) . '"' . $dataOptions . '>
' . $delete . '
' . $select . '
' . (!empty($controlOptions['html']) ? $controlOptions['html'] : '') . '
';
$popupOutput = '';
foreach ($popups AS $popup)
{
if ($popup !== '')
{
$popupOutput = $popup . "n" . $popupOutput;
}
}
$output .= $popupOutput;
$output .= '
<h4' . $labelClass . '>' . $toggle . $beforeLabel . '
<a' . $href . $linkClass . $linkStyle . $tooltip . $target . '>
<em>' . $controlOptions['label'] . '</em>' . (!empty($controlOptions['snippet']) ? '
<dfn>' . $controlOptions['snippet'] . '</dfn>' : '') . '
</a></h4>
</li>
';
return $output;
}
/**
* Returns HTML for a quick and simple popup control.
*
* @param array $controlOptions Options for the control
* @param array $choices Choices within the popup; each will be an li
* @param string $wrapTag Tag to wrap menu in (div or ul, for example)
* @param string $extraMenuClass An extra class (or multiple) set as the menu class
*
* @return string Popup HTML
*/
public static function popup(array $controlOptions, array $choices, $wrapTag = 'div', $extraMenuClass = '')
{
// attached to .Popup
$class = (!empty($controlOptions['class']) ? ' ' . $controlOptions['class'] : '');
// attached to control
$ctrlHref = (!empty($controlOptions['href']) ? ' href="' . $controlOptions['href'] . '"' : '');
$ctrlClass = (!empty($controlOptions['ctrlclass']) ? ' class="' . $controlOptions['ctrlclass'] . '"' : '');
// attached to .Menu
$menuClass = (!empty($controlOptions['menuclass']) ? ' ' . $controlOptions['menuclass'] : '');
if ($extraMenuClass)
{
$menuClass .= " $extraMenuClass";
}
$choiceOutput = '';
foreach ($choices AS $choice)
{
if (isset($choice['displayif']) && empty($choice['displayif']))
{
continue;
}
if (isset($choice['html']))
{
$choiceOutput .= "tt<li>$choice[html]</li>n";
}
else
{
$choiceOutput .= "tt<li><a href="$choice[href]">$choice[text]</a></li>n";
}
}
if ($choiceOutput === '')
{
return '';
}
return '
<' . $wrapTag . ' class="Popup' . $class . '">
<a' . $ctrlHref . $ctrlClass . ' rel="Menu">' . $controlOptions['title'] . '</a>
<div class="Menu">
<div class="primaryContent menuHeader"><h3>' . $controlOptions['title'] . '</h3></div>
<ul class="secondaryContent blockLinksList ' . $menuClass . '">
' . $choiceOutput . '
</ul>
</div>
</' . $wrapTag . '>
';
}
/**
* Returns the ID used for filter list items and lastHash
*
* @param mixed $id
*
* @return string
*/
public static function getListItemId($id)
{
return ($id !== '' ? '_' . str_replace('.', '-', $id) : '');
}
}