multi_select
Github

	function multi_select() {
		return _class('html')->multi_select_box('input_name', ['k1' => 'key1', 'k2' => 'key2']);
	}
	function multi_select($name, $values = [], $selected = '', $show_text = false, $type = 2, $add_str = '', $translate = 0, $level = 0, $disabled = false) {
		// Passing params as array
		if (is_array($name)) {
			$extra = (array)$extra + $name;
			$name = $extra['name'];
		}
		$values = isset($extra['values']) ? $extra['values'] : (array)$values; // Required
		$translate = isset($extra['translate']) ? $extra['translate'] : $translate;
		if ($extra['no_translate']) {
			$translate = 0;
		}
		$selected = isset($extra['selected']) ? $extra['selected'] : $selected;
		$show_text = isset($extra['show_text']) ? $extra['show_text'] : (!is_null($show_text) ? $show_text : false);
		$type = isset($extra['type']) ? $extra['type'] : (!is_null($type) ? $type : 2);
		$level = isset($extra['level']) ? $extra['level'] : $level;
		// (example: $add_str = 'size=6') disabled
		$add_str = isset($extra['add_str']) ? $extra['add_str'] : $add_str;
		$extra['class'] = isset($extra['class']) ? $extra['class'] : $this->CLASS_SELECT_BOX;
		$extra['class_add'] && $extra['class'] = trim($extra['class'].' '.$extra['class_add']);
		if (!$values) {
			return false;
		}
		if ($extra['disabled'] || $disabled) {
			$extra['disabled'] = 'disabled';
		}
		if (!is_array($selected)) {
			$selected = strval($selected);
		}
		$body = [];
		if ($level == 0) {
			$extra['force_id'] && $id = $extra['force_id'];
			$id = $id ?: __FUNCTION__.'_'.++$this->_ids[__FUNCTION__];
			if ($this->AUTO_ASSIGN_IDS) {
				$extra['id'] = $id;
			}
			if ($extra['outer_label']) {
				$body[] = '<label class="outer-label">'.$extra['outer_label'].'</label>';
			}
			$extra['multiple'] = 'multiple';
			$extra['name'] = $name ? $name.'[]' : '';
			$body[] = '<select'._attrs($extra, ['name','id','class','style','multiple','disabled','required']). ($add_str ? ' '.trim($add_str) : '').'>';
		}
		if ($show_text && $level == 0) {
			$def_opt_text = $show_text;
			if ($show_text == 1) {
				$def_opt_text = str_replace(['%name%','%select%'], [t($name), t('Select')], $this->SELECT_BOX_DEF_OPT_TPL);
			}
			$body[] = '<option value="" class="'.$this->CLASS_SELECT_OPTION_DEFAULT.'">'. $def_opt_text. '</option>';
		}
		$self_func = __FUNCTION__;
		foreach ((array)$values as $key => $value) {
			if (is_array($value)) {
				$body[] = '<optgroup label="'.$key.'" title="'.($translate ? t($key) : $key).'">';
				$body[] = $this->$self_func($name, $value, $selected, $show_text, $type, $add_str, $translate, $level + 1);
				$body[] = '</optgroup>';
			} else {
				// Selected value could be an array
				if (is_array($selected)) {
					if ($type == 1) {
						$sel_text = in_array($key, $selected) ? 'selected="selected"' : '';
					} else {
						$sel_text = isset($selected[$key]) ? 'selected="selected"' : '';
					}
				} elseif (strlen($selected)) {
					$_what_compare = strval($type == 1 ? $value : $key);
					$sel_text = $_what_compare == $selected ? 'selected="selected"' : '';
				} else {
					$sel_text = '';
				}
				$body[] = '<option value="'.$key.'"'.($sel_text ? ' '.$sel_text : '').'>'.($translate ? t($value) : $value).'</option>';
			}
		}
		$body[] = $level == 0 ? '</select>' : '';
		return implode(PHP_EOL, $body);
	}