Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
      • Traits
    • Reflection
    • Security
    • Tokenizer
    • Utils
  • Tracy
    • Bridges
      • Nette
  • none

Classes

  • Container
  • ControlGroup
  • Form
  • Helpers
  • Rule
  • Rules
  • Validator

Interfaces

  • IControl
  • IFormRenderer
  • ISubmitterControl
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\Forms;
  9: 
 10: use Nette;
 11: use Nette\Utils\Html;
 12: use Nette\Utils\Strings;
 13: 
 14: 
 15: /**
 16:  * Forms helpers.
 17:  */
 18: class Helpers
 19: {
 20:     use Nette\StaticClass;
 21: 
 22:     private static $unsafeNames = [
 23:         'attributes', 'children', 'elements', 'focus', 'length', 'reset', 'style', 'submit', 'onsubmit', 'form',
 24:         'presenter', 'action',
 25:     ];
 26: 
 27: 
 28:     /**
 29:      * Extracts and sanitizes submitted form data for single control.
 30:      * @param  array
 31:      * @param  string
 32:      * @param  int  type Form::DATA_TEXT, DATA_LINE, DATA_FILE, DATA_KEYS
 33:      * @return string|string[]
 34:      * @internal
 35:      */
 36:     public static function extractHttpData(array $data, $htmlName, $type)
 37:     {
 38:         $name = explode('[', str_replace(['[]', ']', '.'], ['', '', '_'], $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 [];
 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((string) $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:      * Converts control name to HTML name.
 81:      * @return string
 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:      * @return array
 98:      */
 99:     public static function exportRules(Rules $rules)
100:     {
101:         $payload = [];
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 = [
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:                 } elseif (!$item['rules']) {
118:                     continue;
119:                 }
120:             } else {
121:                 $item = ['op' => ($rule->isNegative ? '~' : '') . $op, 'msg' => Validator::formatMessage($rule, false)];
122:             }
123: 
124:             if (is_array($rule->arg)) {
125:                 $item['arg'] = [];
126:                 foreach ($rule->arg as $key => $value) {
127:                     $item['arg'][$key] = $value instanceof IControl ? ['control' => $value->getHtmlName()] : $value;
128:                 }
129:             } elseif ($rule->arg !== null) {
130:                 $item['arg'] = $rule->arg instanceof IControl ? ['control' => $rule->arg->getHtmlName()] : $rule->arg;
131:             }
132: 
133:             $payload[] = $item;
134:         }
135:         if ($payload && $rules->isOptional()) {
136:             array_unshift($payload, ['op' => 'optional']);
137:         }
138:         return $payload;
139:     }
140: 
141: 
142:     /**
143:      * @return string
144:      */
145:     public static function createInputList(array $items, array $inputAttrs = null, array $labelAttrs = null, $wrapper = null)
146:     {
147:         list($inputAttrs, $inputTag) = self::prepareAttrs($inputAttrs, 'input');
148:         list($labelAttrs, $labelTag) = self::prepareAttrs($labelAttrs, 'label');
149:         $res = '';
150:         $input = Html::el();
151:         $label = Html::el();
152:         list($wrapper, $wrapperEnd) = $wrapper instanceof Html ? [$wrapper->startTag(), $wrapper->endTag()] : [(string) $wrapper, ''];
153: 
154:         foreach ($items as $value => $caption) {
155:             foreach ($inputAttrs as $k => $v) {
156:                 $input->attrs[$k] = isset($v[$value]) ? $v[$value] : null;
157:             }
158:             foreach ($labelAttrs as $k => $v) {
159:                 $label->attrs[$k] = isset($v[$value]) ? $v[$value] : null;
160:             }
161:             $input->value = $value;
162:             $res .= ($res === '' && $wrapperEnd === '' ? '' : $wrapper)
163:                 . $labelTag . $label->attributes() . '>'
164:                 . $inputTag . $input->attributes() . (Html::$xhtml ? ' />' : '>')
165:                 . ($caption instanceof Nette\Utils\IHtmlString ? $caption : htmlspecialchars($caption, ENT_NOQUOTES, 'UTF-8'))
166:                 . '</label>'
167:                 . $wrapperEnd;
168:         }
169:         return $res;
170:     }
171: 
172: 
173:     /**
174:      * @return Html
175:      */
176:     public static function createSelectBox(array $items, array $optionAttrs = null, $selected = null)
177:     {
178:         if ($selected !== null) {
179:             $optionAttrs['selected?'] = $selected;
180:         }
181:         list($optionAttrs, $optionTag) = self::prepareAttrs($optionAttrs, 'option');
182:         $option = Html::el();
183:         $res = $tmp = '';
184:         foreach ($items as $group => $subitems) {
185:             if (is_array($subitems)) {
186:                 $res .= Html::el('optgroup')->label($group)->startTag();
187:                 $tmp = '</optgroup>';
188:             } else {
189:                 $subitems = [$group => $subitems];
190:             }
191:             foreach ($subitems as $value => $caption) {
192:                 $option->value = $value;
193:                 foreach ($optionAttrs as $k => $v) {
194:                     $option->attrs[$k] = isset($v[$value]) ? $v[$value] : null;
195:                 }
196:                 if ($caption instanceof Html) {
197:                     $caption = clone $caption;
198:                     $res .= $caption->setName('option')->addAttributes($option->attrs);
199:                 } else {
200:                     $res .= $optionTag . $option->attributes() . '>'
201:                         . htmlspecialchars((string) $caption, ENT_NOQUOTES, 'UTF-8')
202:                         . '</option>';
203:                 }
204:                 if ($selected === $value) {
205:                     unset($optionAttrs['selected'], $option->attrs['selected']);
206:                 }
207:             }
208:             $res .= $tmp;
209:             $tmp = '';
210:         }
211:         return Html::el('select')->setHtml($res);
212:     }
213: 
214: 
215:     private static function prepareAttrs($attrs, $name)
216:     {
217:         $dynamic = [];
218:         foreach ((array) $attrs as $k => $v) {
219:             $p = str_split($k, strlen($k) - 1);
220:             if ($p[1] === '?' || $p[1] === ':') {
221:                 unset($attrs[$k], $attrs[$p[0]]);
222:                 if ($p[1] === '?') {
223:                     $dynamic[$p[0]] = array_fill_keys((array) $v, true);
224:                 } elseif (is_array($v) && $v) {
225:                     $dynamic[$p[0]] = $v;
226:                 } else {
227:                     $attrs[$p[0]] = $v;
228:                 }
229:             }
230:         }
231:         return [$dynamic, '<' . $name . Html::el(null, $attrs)->attributes()];
232:     }
233: }
234: 
Nette 2.4-20180918 API API documentation generated by ApiGen 2.8.0