Show:

File: platform/plugins/Q/handlers/Q/form/tool.php

<?php

/**
 * @module Q-tools
 */

/**
 * This tool is meant to be wrapped in a <form> tag
 * @class Q form
 * @constructor
 * @param {array} $options An associative array of parameters, containing:
 * @param {array} $options.fields an associative array of fieldname => fieldinfo pairs,
 *   where fieldinfo contains the following:
 *     "type" => the type of the field (@see Q_Html::smartTag())
 *     "attributes" => additional attributes for the field input
 *     "value" => the initial value of the field input
 *     "options" => options for the field input (if type is "select", "checkboxes" or "radios")
 *     "message" => initial message, if any to put in the field's message space
 *     "label" => the label for the field
 *     "extra" => if set, this is html to replace the first cell, displacing the label
 *     "placeholder" => if set, this is the placeholder text for the input
 *     "fillFromRequest" => Defaults to true.
 *       If true, uses $_REQUEST to fill any fields with same name.
 *       Currently doesn't work for names which specify arrays, such as a[b].
 * @param {string} [$options.onSubmit] Optional. Name of the javascript function or url to pass to Q.handle on submit
 * @param {string} [$options.onResponse] Name of the javascript function or url to pass to Q.handle on response
 * @param {string} [$options.onSuccess] Name of javascript function or url to pass to Q.handle on success
 * @param {string} [$options.loader] Optional. Name of a javascript function which takes (action, method, params, slots, callback) as arguments.
 *    It should call the callback and pass it an object with the response info. Can be used to implement caching, etc.
 *    instead of the default HTTP request.
 *    If "loader" is Q.getter and request should be done bypasing cache, assign true to .ignoreCache property of the tool
 * @param {array|string} [$options.slotsToRequest] Optional. A string or array of slot names to request in response. Should include "form".
 * @param {array|string} [$options.contentElements] Optional. Array of $slotName => $cssSelector pairs for child element of the form to fill with HTML returned from the slot.
 */
function Q_form_tool($options)
{
	if (empty($options['fields'])) {
		$options['fields'] = array();
	}
	if (!array_key_exists('fillFromRequest', $options)) {
		$options['fillFromRequest'] = true;
	}
	if (empty($options['contentElements'])) {
		$options['contentElements'] = array();
	}

	$field_defaults = array(
		'type' => 'text',
		'attributes' => array(),
		'value' => null,
		'options' => array(),
		'message' => '',
		'placeholder' => null
	);
	$tr_array = array();
	$messages_td = false;
	$colspan = '';
	foreach ($options['fields'] as $name => $field) {
		if (isset($field['message'])) {
			$messages_td = true;
			$colspan = "colspan='2'";
		}
	}
	foreach ($options['fields'] as $name => $field) {
		if (!is_array($field)) {
			$name2 = '"'.addslashes($name).'"';
			throw new Q_Exception_WrongType(array(
				'field' => "\$options[$name2]",
				'type' => 'array'
			));
		}
		$field2 = array_merge($field_defaults, $field);
		$type = $field2['type'];
		if ($type === 'hidden') {
			continue;
		}
		$attributes = array(
			'name' => $name,
			'id' => $name
		);
		$value = $field2['value'];
		$o = $field2['options'];
		$message = $field2['message'];
		if (!empty($options['fillFromRequest']) and !in_array($type, array('button', 'submit'))) {
			if (isset($_REQUEST[$name])) {
				$value = $_REQUEST[$name];
			} else if ($type === 'static' or $type === 'date') {
				$parts = array(
					$name.'_hour' => 0,
					$name.'_minute' => 0,
					$name.'_second' => 0,
					$name.'_month' => date('m'),
					$name.'_day' => date('d'),
					$name.'_year' => date('Y')
				);
				$provided = Q::ifset($_REQUEST, array_keys($parts), null);
				if (isset($provided)) {
					$mktime = Q::take($_REQUEST, $parts);
					$value = call_user_func_array('mktime', $mktime);
				}
			}
		}
		if (isset($field2['placeholder'])) {
			$attributes['placeholder'] = $field2['placeholder'];
		}
		if ($field2['attributes']) {
			$attributes = array_merge($attributes, $field2['attributes']);
		}
		if (ctype_alnum($type)) {
			if (isset($attributes['class'])) {
				if (is_array($attributes['class'])) {
					foreach ($attributes['class'] as $k => $v) {
						$attributes['class'][$k] .= " $type";
					}
				} else {
					$attributes['class'] .= " $type";
				}
			} else {
				$attributes['class'] = " $type";
			}
		}
		$label = isset($field['label']) ? $field['label'] : Q_Html::text($name);
		$label = Q_Html::tag('label', array('for' => $attributes['id']), $label);
		$name_text = Q_Html::text($name);
		$extra = isset($field['extra']) ? $field['extra'] : null;
		switch ($type) {
			case 'textarea':
				$tr_rest = "<td class='Q_form_fieldinput' data-fieldname=\"$name_text\" $colspan>"
					. ($extra ? "<div class='Q_form_label'>$label</div>" : '')
					. Q_Html::smartTag($type, $attributes, $value, $o)
					. "</td></tr><tr><td class='Q_form_placeholder'>"
					. "</td><td class='Q_form_undermessage Q_form_textarea_undermessage' $colspan>"
					. "<div class='Q_form_undermessagebubble'>$message</div></td>";
				break;
			default:
				$tr_rest = "<td class='Q_form_fieldinput' data-fieldname=\"$name_text\">"
					. ($extra ? "<div class='Q_form_label'>$label</div>" : '')
 					. Q_Html::smartTag($type, $attributes, $value, $o)
 					. "</td>"
					. ($messages_td
						? "<td class='Q_form_fieldmessage Q_form_{$type}_message'>$message</td>"
						: '')
					. "</tr><tr><td class='Q_form_placeholder'>"
					. "</td><td class='Q_form_undermessage Q_form_{$type}_undermessage' $colspan>"
					. "<div class='Q_form_undermessagebubble'></div></td>";
				break;
		}
		$leftside = $extra ? $extra : $label;
		$tr_array[] = "<tr><td class='Q_form_fieldname'>$leftside</td>$tr_rest</tr>";
	}
	$result = "<table class='Q_form_tool_table'>\n"
		.implode("\n\t", $tr_array)
		."\n</table>";
	foreach ($options['fields'] as $name => $field) {
 		if (isset($field['type']) and $field['type'] === 'hidden') {
			$result .= Q_Html::hidden($field['value'], $name);
		}
	}
	$fields = array('onSubmit', 'onResponse', 'onSuccess', 'slotsToRequest', 'loader', 'contentElements');
	Q_Response::setToolOptions(Q::take($options, $fields));
	Q_Response::addScript('{{Q}}/js/tools/form.js', 'Q');
	Q_Response::addStylesheet('{{Q}}/css/form.css', 'Q');
	return $result;
}