1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Forms;
9:
10: use Nette,
11: Nette\Utils\Strings,
12: Nette\Utils\Html;
13:
14:
15: 16: 17: 18: 19:
20: class Helpers extends Nette\Object
21: {
22: private static $unsafeNames = array(
23: 'attributes', 'children', 'elements', 'focus', 'length', 'reset', 'style', 'submit', 'onsubmit', 'form',
24: 'presenter', 'action',
25: );
26:
27:
28: 29: 30: 31: 32: 33: 34: 35:
36: public static function (array $data, $htmlName, $type)
37: {
38: $name = explode('[', str_replace(array('[]', ']', '.'), array('', '', '_'), $htmlName));
39: $data = Nette\Utils\Arrays::get($data, $name, NULL);
40: $itype = $type & ~Form::DATA_KEYS;
41:
42: if (substr($htmlName, -2) === '[]') {
43: if (!is_array($data)) {
44: return array();
45: }
46: foreach ($data as $k => $v) {
47: $data[$k] = $v = static::sanitize($itype, $v);
48: if ($v === NULL) {
49: unset($data[$k]);
50: }
51: }
52: if ($type & Form::DATA_KEYS) {
53: return $data;
54: }
55: return array_values($data);
56: } else {
57: return static::sanitize($itype, $data);
58: }
59: }
60:
61:
62: private static function sanitize($type, $value)
63: {
64: if ($type === Form::DATA_TEXT) {
65: return is_scalar($value) ? Strings::normalizeNewLines($value) : NULL;
66:
67: } elseif ($type === Form::DATA_LINE) {
68: return is_scalar($value) ? Strings::trim(strtr($value, "\r\n", ' ')) : NULL;
69:
70: } elseif ($type === Form::DATA_FILE) {
71: return $value instanceof Nette\Http\FileUpload ? $value : NULL;
72:
73: } else {
74: throw new Nette\InvalidArgumentException('Unknown data type');
75: }
76: }
77:
78:
79: 80: 81: 82:
83: public static function generateHtmlName($id)
84: {
85: $name = str_replace(Nette\ComponentModel\IComponent::NAME_SEPARATOR, '][', $id, $count);
86: if ($count) {
87: $name = substr_replace($name, '', strpos($name, ']'), 1) . ']';
88: }
89: if (is_numeric($name) || in_array($name, self::$unsafeNames, TRUE)) {
90: $name = '_' . $name;
91: }
92: return $name;
93: }
94:
95:
96: 97: 98:
99: public static function exportRules(Rules $rules)
100: {
101: $payload = array();
102: foreach ($rules as $rule) {
103: if (!is_string($op = $rule->validator)) {
104: if (!Nette\Utils\Callback::isStatic($op)) {
105: continue;
106: }
107: $op = Nette\Utils\Callback::toString($op);
108: }
109: if ($rule->branch) {
110: $item = array(
111: 'op' => ($rule->isNegative ? '~' : '') . $op,
112: 'rules' => static::exportRules($rule->branch),
113: 'control' => $rule->control->getHtmlName()
114: );
115: if ($rule->branch->getToggles()) {
116: $item['toggle'] = $rule->branch->getToggles();
117: }
118: } else {
119: $item = array('op' => ($rule->isNegative ? '~' : '') . $op, 'msg' => Validator::formatMessage($rule, FALSE));
120: }
121:
122: if (is_array($rule->arg)) {
123: foreach ($rule->arg as $key => $value) {
124: $item['arg'][$key] = $value instanceof IControl ? array('control' => $value->getHtmlName()) : $value;
125: }
126: } elseif ($rule->arg !== NULL) {
127: $item['arg'] = $rule->arg instanceof IControl ? array('control' => $rule->arg->getHtmlName()) : $rule->arg;
128: }
129:
130: $payload[] = $item;
131: }
132: return $payload;
133: }
134:
135:
136: 137: 138:
139: public static function createInputList(array $items, array $inputAttrs = NULL, array $labelAttrs = NULL, $wrapper = NULL)
140: {
141: list($inputAttrs, $inputTag) = self::prepareAttrs($inputAttrs, 'input');
142: list($labelAttrs, $labelTag) = self::prepareAttrs($labelAttrs, 'label');
143: $res = '';
144: $input = Html::el();
145: $label = Html::el();
146: list($wrapper, $wrapperEnd) = $wrapper instanceof Html ? array($wrapper->startTag(), $wrapper->endTag()) : array((string) $wrapper, '');
147:
148: foreach ($items as $value => $caption) {
149: foreach ($inputAttrs as $k => $v) {
150: $input->attrs[$k] = isset($v[$value]) ? $v[$value] : NULL;
151: }
152: foreach ($labelAttrs as $k => $v) {
153: $label->attrs[$k] = isset($v[$value]) ? $v[$value] : NULL;
154: }
155: $input->value = $value;
156: $res .= ($res === '' && $wrapperEnd === '' ? '' : $wrapper)
157: . $labelTag . $label->attributes() . '>'
158: . $inputTag . $input->attributes() . (Html::$xhtml ? ' />' : '>')
159: . ($caption instanceof Html ? $caption : htmlspecialchars($caption, ENT_NOQUOTES, 'UTF-8'))
160: . '</label>'
161: . $wrapperEnd;
162: }
163: return $res;
164: }
165:
166:
167: 168: 169:
170: public static function createSelectBox(array $items, array $optionAttrs = NULL)
171: {
172: list($optionAttrs, $optionTag) = self::prepareAttrs($optionAttrs, 'option');
173: $option = Html::el();
174: $res = $tmp = '';
175: foreach ($items as $group => $subitems) {
176: if (is_array($subitems)) {
177: $res .= Html::el('optgroup')->label($group)->startTag();
178: $tmp = '</optgroup>';
179: } else {
180: $subitems = array($group => $subitems);
181: }
182: foreach ($subitems as $value => $caption) {
183: $option->value = $value;
184: foreach ($optionAttrs as $k => $v) {
185: $option->attrs[$k] = isset($v[$value]) ? $v[$value] : NULL;
186: }
187: if ($caption instanceof Html) {
188: $caption = clone $caption;
189: $res .= $caption->setName('option')->addAttributes($option->attrs);
190: } else {
191: $res .= $optionTag . $option->attributes() . '>'
192: . htmlspecialchars($caption, ENT_NOQUOTES, 'UTF-8')
193: . '</option>';
194: }
195: }
196: $res .= $tmp;
197: $tmp = '';
198: }
199: return Html::el('select')->setHtml($res);
200: }
201:
202:
203: private static function prepareAttrs($attrs, $name)
204: {
205: $dynamic = array();
206: foreach ((array) $attrs as $k => $v) {
207: $p = str_split($k, strlen($k) - 1);
208: if ($p[1] === '?' || $p[1] === ':') {
209: unset($attrs[$k], $attrs[$p[0]]);
210: if ($p[1] === '?') {
211: $dynamic[$p[0]] = array_fill_keys((array) $v, TRUE);
212: } elseif (is_array($v) && $v) {
213: $dynamic[$p[0]] = $v;
214: } else {
215: $attrs[$p[0]] = $v;
216: }
217: }
218: }
219: return array($dynamic, '<' . $name . Html::el(NULL, $attrs)->attributes());
220: }
221:
222: }
223: