├── FormFacade.php ├── HtmlFacade.php ├── composer.json ├── HtmlServiceProvider.php ├── helpers.php ├── HtmlBuilder.php └── FormBuilder.php /FormFacade.php: -------------------------------------------------------------------------------- 1 | =5.4.0", 12 | "illuminate/http": "~5.0", 13 | "illuminate/session": "~5.0", 14 | "illuminate/support": "~5.0" 15 | }, 16 | "autoload": { 17 | "psr-4": { 18 | "Illuminate\\Html\\": "" 19 | }, 20 | "files": [ 21 | "helpers.php" 22 | ] 23 | }, 24 | "extra": { 25 | "branch-alias": { 26 | "dev-master": "5.0-dev" 27 | } 28 | }, 29 | "minimum-stability": "dev" 30 | } 31 | -------------------------------------------------------------------------------- /HtmlServiceProvider.php: -------------------------------------------------------------------------------- 1 | registerHtmlBuilder(); 22 | 23 | $this->registerFormBuilder(); 24 | 25 | $this->app->alias('html', 'Illuminate\Html\HtmlBuilder'); 26 | $this->app->alias('form', 'Illuminate\Html\FormBuilder'); 27 | } 28 | 29 | /** 30 | * Register the HTML builder instance. 31 | * 32 | * @return void 33 | */ 34 | protected function registerHtmlBuilder() 35 | { 36 | $this->app->bindShared('html', function($app) 37 | { 38 | return new HtmlBuilder($app['url']); 39 | }); 40 | } 41 | 42 | /** 43 | * Register the form builder instance. 44 | * 45 | * @return void 46 | */ 47 | protected function registerFormBuilder() 48 | { 49 | $this->app->bindShared('form', function($app) 50 | { 51 | $form = new FormBuilder($app['html'], $app['url'], $app['session.store']->getToken()); 52 | 53 | return $form->setSessionStore($app['session.store']); 54 | }); 55 | } 56 | 57 | /** 58 | * Get the services provided by the provider. 59 | * 60 | * @return array 61 | */ 62 | public function provides() 63 | { 64 | return array('html', 'form'); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /helpers.php: -------------------------------------------------------------------------------- 1 | link($url, $title, $attributes, $secure); 17 | } 18 | } 19 | 20 | if ( ! function_exists('link_to_asset')) 21 | { 22 | /** 23 | * Generate a HTML link to an asset. 24 | * 25 | * @param string $url 26 | * @param string $title 27 | * @param array $attributes 28 | * @param bool $secure 29 | * @return string 30 | */ 31 | function link_to_asset($url, $title = null, $attributes = array(), $secure = null) 32 | { 33 | return app('html')->linkAsset($url, $title, $attributes, $secure); 34 | } 35 | } 36 | 37 | if ( ! function_exists('link_to_route')) 38 | { 39 | /** 40 | * Generate a HTML link to a named route. 41 | * 42 | * @param string $name 43 | * @param string $title 44 | * @param array $parameters 45 | * @param array $attributes 46 | * @return string 47 | */ 48 | function link_to_route($name, $title = null, $parameters = array(), $attributes = array()) 49 | { 50 | return app('html')->linkRoute($name, $title, $parameters, $attributes); 51 | } 52 | } 53 | 54 | if ( ! function_exists('link_to_action')) 55 | { 56 | /** 57 | * Generate a HTML link to a controller action. 58 | * 59 | * @param string $action 60 | * @param string $title 61 | * @param array $parameters 62 | * @param array $attributes 63 | * @return string 64 | */ 65 | function link_to_action($action, $title = null, $parameters = array(), $attributes = array()) 66 | { 67 | return app('html')->linkAction($action, $title, $parameters, $attributes); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /HtmlBuilder.php: -------------------------------------------------------------------------------- 1 | url = $url; 26 | } 27 | 28 | /** 29 | * Convert an HTML string to entities. 30 | * 31 | * @param string $value 32 | * @return string 33 | */ 34 | public function entities($value) 35 | { 36 | return htmlentities($value, ENT_QUOTES, 'UTF-8', false); 37 | } 38 | 39 | /** 40 | * Convert entities to HTML characters. 41 | * 42 | * @param string $value 43 | * @return string 44 | */ 45 | public function decode($value) 46 | { 47 | return html_entity_decode($value, ENT_QUOTES, 'UTF-8'); 48 | } 49 | 50 | /** 51 | * Generate a link to a JavaScript file. 52 | * 53 | * @param string $url 54 | * @param array $attributes 55 | * @param bool $secure 56 | * @return string 57 | */ 58 | public function script($url, $attributes = array(), $secure = null) 59 | { 60 | $attributes['src'] = $this->url->asset($url, $secure); 61 | 62 | return 'attributes($attributes).'>'.PHP_EOL; 63 | } 64 | 65 | /** 66 | * Generate a link to a CSS file. 67 | * 68 | * @param string $url 69 | * @param array $attributes 70 | * @param bool $secure 71 | * @return string 72 | */ 73 | public function style($url, $attributes = array(), $secure = null) 74 | { 75 | $defaults = array('media' => 'all', 'type' => 'text/css', 'rel' => 'stylesheet'); 76 | 77 | $attributes = $attributes + $defaults; 78 | 79 | $attributes['href'] = $this->url->asset($url, $secure); 80 | 81 | return 'attributes($attributes).'>'.PHP_EOL; 82 | } 83 | 84 | /** 85 | * Generate an HTML image element. 86 | * 87 | * @param string $url 88 | * @param string $alt 89 | * @param array $attributes 90 | * @param bool $secure 91 | * @return string 92 | */ 93 | public function image($url, $alt = null, $attributes = array(), $secure = null) 94 | { 95 | $attributes['alt'] = $alt; 96 | 97 | return 'attributes($attributes).'>'; 98 | } 99 | 100 | /** 101 | * Generate a HTML link. 102 | * 103 | * @param string $url 104 | * @param string $title 105 | * @param array $attributes 106 | * @param bool $secure 107 | * @return string 108 | */ 109 | public function link($url, $title = null, $attributes = array(), $secure = null) 110 | { 111 | $url = $this->url->to($url, array(), $secure); 112 | 113 | if (is_null($title) || $title === false) $title = $url; 114 | 115 | return 'attributes($attributes).'>'.$this->entities($title).''; 116 | } 117 | 118 | /** 119 | * Generate a HTTPS HTML link. 120 | * 121 | * @param string $url 122 | * @param string $title 123 | * @param array $attributes 124 | * @return string 125 | */ 126 | public function secureLink($url, $title = null, $attributes = array()) 127 | { 128 | return $this->link($url, $title, $attributes, true); 129 | } 130 | 131 | /** 132 | * Generate a HTML link to an asset. 133 | * 134 | * @param string $url 135 | * @param string $title 136 | * @param array $attributes 137 | * @param bool $secure 138 | * @return string 139 | */ 140 | public function linkAsset($url, $title = null, $attributes = array(), $secure = null) 141 | { 142 | $url = $this->url->asset($url, $secure); 143 | 144 | return $this->link($url, $title ?: $url, $attributes, $secure); 145 | } 146 | 147 | /** 148 | * Generate a HTTPS HTML link to an asset. 149 | * 150 | * @param string $url 151 | * @param string $title 152 | * @param array $attributes 153 | * @return string 154 | */ 155 | public function linkSecureAsset($url, $title = null, $attributes = array()) 156 | { 157 | return $this->linkAsset($url, $title, $attributes, true); 158 | } 159 | 160 | /** 161 | * Generate a HTML link to a named route. 162 | * 163 | * @param string $name 164 | * @param string $title 165 | * @param array $parameters 166 | * @param array $attributes 167 | * @return string 168 | */ 169 | public function linkRoute($name, $title = null, $parameters = array(), $attributes = array()) 170 | { 171 | return $this->link($this->url->route($name, $parameters), $title, $attributes); 172 | } 173 | 174 | /** 175 | * Generate a HTML link to a controller action. 176 | * 177 | * @param string $action 178 | * @param string $title 179 | * @param array $parameters 180 | * @param array $attributes 181 | * @return string 182 | */ 183 | public function linkAction($action, $title = null, $parameters = array(), $attributes = array()) 184 | { 185 | return $this->link($this->url->action($action, $parameters), $title, $attributes); 186 | } 187 | 188 | /** 189 | * Generate a HTML link to an email address. 190 | * 191 | * @param string $email 192 | * @param string $title 193 | * @param array $attributes 194 | * @return string 195 | */ 196 | public function mailto($email, $title = null, $attributes = array()) 197 | { 198 | $email = $this->email($email); 199 | 200 | $title = $title ?: $email; 201 | 202 | $email = $this->obfuscate('mailto:') . $email; 203 | 204 | return 'attributes($attributes).'>'.$this->entities($title).''; 205 | } 206 | 207 | /** 208 | * Obfuscate an e-mail address to prevent spam-bots from sniffing it. 209 | * 210 | * @param string $email 211 | * @return string 212 | */ 213 | public function email($email) 214 | { 215 | return str_replace('@', '@', $this->obfuscate($email)); 216 | } 217 | 218 | /** 219 | * Generate an ordered list of items. 220 | * 221 | * @param array $list 222 | * @param array $attributes 223 | * @return string 224 | */ 225 | public function ol($list, $attributes = array()) 226 | { 227 | return $this->listing('ol', $list, $attributes); 228 | } 229 | 230 | /** 231 | * Generate an un-ordered list of items. 232 | * 233 | * @param array $list 234 | * @param array $attributes 235 | * @return string 236 | */ 237 | public function ul($list, $attributes = array()) 238 | { 239 | return $this->listing('ul', $list, $attributes); 240 | } 241 | 242 | /** 243 | * Create a listing HTML element. 244 | * 245 | * @param string $type 246 | * @param array $list 247 | * @param array $attributes 248 | * @return string 249 | */ 250 | protected function listing($type, $list, $attributes = array()) 251 | { 252 | $html = ''; 253 | 254 | if (count($list) == 0) return $html; 255 | 256 | // Essentially we will just spin through the list and build the list of the HTML 257 | // elements from the array. We will also handled nested lists in case that is 258 | // present in the array. Then we will build out the final listing elements. 259 | foreach ($list as $key => $value) 260 | { 261 | $html .= $this->listingElement($key, $type, $value); 262 | } 263 | 264 | $attributes = $this->attributes($attributes); 265 | 266 | return "<{$type}{$attributes}>{$html}"; 267 | } 268 | 269 | /** 270 | * Create the HTML for a listing element. 271 | * 272 | * @param mixed $key 273 | * @param string $type 274 | * @param string $value 275 | * @return string 276 | */ 277 | protected function listingElement($key, $type, $value) 278 | { 279 | if (is_array($value)) 280 | { 281 | return $this->nestedListing($key, $type, $value); 282 | } 283 | else 284 | { 285 | return '
  • '.e($value).'
  • '; 286 | } 287 | } 288 | 289 | /** 290 | * Create the HTML for a nested listing attribute. 291 | * 292 | * @param mixed $key 293 | * @param string $type 294 | * @param string $value 295 | * @return string 296 | */ 297 | protected function nestedListing($key, $type, $value) 298 | { 299 | if (is_int($key)) 300 | { 301 | return $this->listing($type, $value); 302 | } 303 | else 304 | { 305 | return '
  • '.$key.$this->listing($type, $value).'
  • '; 306 | } 307 | } 308 | 309 | /** 310 | * Build an HTML attribute string from an array. 311 | * 312 | * @param array $attributes 313 | * @return string 314 | */ 315 | public function attributes($attributes) 316 | { 317 | $html = array(); 318 | 319 | // For numeric keys we will assume that the key and the value are the same 320 | // as this will convert HTML attributes such as "required" to a correct 321 | // form like required="required" instead of using incorrect numerics. 322 | foreach ((array) $attributes as $key => $value) 323 | { 324 | $element = $this->attributeElement($key, $value); 325 | 326 | if ( ! is_null($element)) $html[] = $element; 327 | } 328 | 329 | return count($html) > 0 ? ' '.implode(' ', $html) : ''; 330 | } 331 | 332 | /** 333 | * Build a single attribute element. 334 | * 335 | * @param string $key 336 | * @param string $value 337 | * @return string 338 | */ 339 | protected function attributeElement($key, $value) 340 | { 341 | if (is_numeric($key)) $key = $value; 342 | 343 | if ( ! is_null($value)) return $key.'="'.e($value).'"'; 344 | } 345 | 346 | /** 347 | * Obfuscate a string to prevent spam-bots from sniffing it. 348 | * 349 | * @param string $value 350 | * @return string 351 | */ 352 | public function obfuscate($value) 353 | { 354 | $safe = ''; 355 | 356 | foreach (str_split($value) as $letter) 357 | { 358 | if (ord($letter) > 128) return $letter; 359 | 360 | // To properly obfuscate the value, we will randomly convert each letter to 361 | // its entity or hexadecimal representation, keeping a bot from sniffing 362 | // the randomly obfuscated letters out of the string on the responses. 363 | switch (rand(1, 3)) 364 | { 365 | case 1: 366 | $safe .= '&#'.ord($letter).';'; break; 367 | 368 | case 2: 369 | $safe .= '&#x'.dechex(ord($letter)).';'; break; 370 | 371 | case 3: 372 | $safe .= $letter; 373 | } 374 | } 375 | 376 | return $safe; 377 | } 378 | 379 | } 380 | -------------------------------------------------------------------------------- /FormBuilder.php: -------------------------------------------------------------------------------- 1 | url = $url; 85 | $this->html = $html; 86 | $this->csrfToken = $csrfToken; 87 | } 88 | 89 | /** 90 | * Open up a new HTML form. 91 | * 92 | * @param array $options 93 | * @return string 94 | */ 95 | public function open(array $options = array()) 96 | { 97 | $method = array_get($options, 'method', 'post'); 98 | 99 | // We need to extract the proper method from the attributes. If the method is 100 | // something other than GET or POST we'll use POST since we will spoof the 101 | // actual method since forms don't support the reserved methods in HTML. 102 | $attributes['method'] = $this->getMethod($method); 103 | 104 | $attributes['action'] = $this->getAction($options); 105 | 106 | $attributes['accept-charset'] = 'UTF-8'; 107 | 108 | // If the method is PUT, PATCH or DELETE we will need to add a spoofer hidden 109 | // field that will instruct the Symfony request to pretend the method is a 110 | // different method than it actually is, for convenience from the forms. 111 | $append = $this->getAppendage($method); 112 | 113 | if (isset($options['files']) && $options['files']) 114 | { 115 | $options['enctype'] = 'multipart/form-data'; 116 | } 117 | 118 | // Finally we're ready to create the final form HTML field. We will attribute 119 | // format the array of attributes. We will also add on the appendage which 120 | // is used to spoof requests for this PUT, PATCH, etc. methods on forms. 121 | $attributes = array_merge( 122 | 123 | $attributes, array_except($options, $this->reserved) 124 | 125 | ); 126 | 127 | // Finally, we will concatenate all of the attributes into a single string so 128 | // we can build out the final form open statement. We'll also append on an 129 | // extra value for the hidden _method field if it's needed for the form. 130 | $attributes = $this->html->attributes($attributes); 131 | 132 | return ''.$append; 133 | } 134 | 135 | /** 136 | * Create a new model based form builder. 137 | * 138 | * @param mixed $model 139 | * @param array $options 140 | * @return string 141 | */ 142 | public function model($model, array $options = array()) 143 | { 144 | $this->model = $model; 145 | 146 | return $this->open($options); 147 | } 148 | 149 | /** 150 | * Set the model instance on the form builder. 151 | * 152 | * @param mixed $model 153 | * @return void 154 | */ 155 | public function setModel($model) 156 | { 157 | $this->model = $model; 158 | } 159 | 160 | /** 161 | * Close the current form. 162 | * 163 | * @return string 164 | */ 165 | public function close() 166 | { 167 | $this->labels = array(); 168 | 169 | $this->model = null; 170 | 171 | return ''; 172 | } 173 | 174 | /** 175 | * Generate a hidden field with the current CSRF token. 176 | * 177 | * @return string 178 | */ 179 | public function token() 180 | { 181 | $token = ! empty($this->csrfToken) ? $this->csrfToken : $this->session->getToken(); 182 | 183 | return $this->hidden('_token', $token); 184 | } 185 | 186 | /** 187 | * Create a form label element. 188 | * 189 | * @param string $name 190 | * @param string $value 191 | * @param array $options 192 | * @return string 193 | */ 194 | public function label($name, $value = null, $options = array()) 195 | { 196 | $this->labels[] = $name; 197 | 198 | $options = $this->html->attributes($options); 199 | 200 | $value = e($this->formatLabel($name, $value)); 201 | 202 | return ''; 203 | } 204 | 205 | /** 206 | * Format the label value. 207 | * 208 | * @param string $name 209 | * @param string|null $value 210 | * @return string 211 | */ 212 | protected function formatLabel($name, $value) 213 | { 214 | return $value ?: ucwords(str_replace('_', ' ', $name)); 215 | } 216 | 217 | /** 218 | * Create a form input field. 219 | * 220 | * @param string $type 221 | * @param string $name 222 | * @param string $value 223 | * @param array $options 224 | * @return string 225 | */ 226 | public function input($type, $name, $value = null, $options = array()) 227 | { 228 | if ( ! isset($options['name'])) $options['name'] = $name; 229 | 230 | // We will get the appropriate value for the given field. We will look for the 231 | // value in the session for the value in the old input data then we'll look 232 | // in the model instance if one is set. Otherwise we will just use empty. 233 | $id = $this->getIdAttribute($name, $options); 234 | 235 | if ( ! in_array($type, $this->skipValueTypes)) 236 | { 237 | $value = $this->getValueAttribute($name, $value); 238 | } 239 | 240 | // Once we have the type, value, and ID we can merge them into the rest of the 241 | // attributes array so we can convert them into their HTML attribute format 242 | // when creating the HTML element. Then, we will return the entire input. 243 | $merge = compact('type', 'value', 'id'); 244 | 245 | $options = array_merge($options, $merge); 246 | 247 | return 'html->attributes($options).'>'; 248 | } 249 | 250 | /** 251 | * Create a text input field. 252 | * 253 | * @param string $name 254 | * @param string $value 255 | * @param array $options 256 | * @return string 257 | */ 258 | public function text($name, $value = null, $options = array()) 259 | { 260 | return $this->input('text', $name, $value, $options); 261 | } 262 | 263 | /** 264 | * Create a password input field. 265 | * 266 | * @param string $name 267 | * @param array $options 268 | * @return string 269 | */ 270 | public function password($name, $options = array()) 271 | { 272 | return $this->input('password', $name, '', $options); 273 | } 274 | 275 | /** 276 | * Create a hidden input field. 277 | * 278 | * @param string $name 279 | * @param string $value 280 | * @param array $options 281 | * @return string 282 | */ 283 | public function hidden($name, $value = null, $options = array()) 284 | { 285 | return $this->input('hidden', $name, $value, $options); 286 | } 287 | 288 | /** 289 | * Create an e-mail input field. 290 | * 291 | * @param string $name 292 | * @param string $value 293 | * @param array $options 294 | * @return string 295 | */ 296 | public function email($name, $value = null, $options = array()) 297 | { 298 | return $this->input('email', $name, $value, $options); 299 | } 300 | 301 | /** 302 | * Create a url input field. 303 | * 304 | * @param string $name 305 | * @param string $value 306 | * @param array $options 307 | * @return string 308 | */ 309 | public function url($name, $value = null, $options = array()) 310 | { 311 | return $this->input('url', $name, $value, $options); 312 | } 313 | 314 | /** 315 | * Create a file input field. 316 | * 317 | * @param string $name 318 | * @param array $options 319 | * @return string 320 | */ 321 | public function file($name, $options = array()) 322 | { 323 | return $this->input('file', $name, null, $options); 324 | } 325 | 326 | /** 327 | * Create a textarea input field. 328 | * 329 | * @param string $name 330 | * @param string $value 331 | * @param array $options 332 | * @return string 333 | */ 334 | public function textarea($name, $value = null, $options = array()) 335 | { 336 | if ( ! isset($options['name'])) $options['name'] = $name; 337 | 338 | // Next we will look for the rows and cols attributes, as each of these are put 339 | // on the textarea element definition. If they are not present, we will just 340 | // assume some sane default values for these attributes for the developer. 341 | $options = $this->setTextAreaSize($options); 342 | 343 | $options['id'] = $this->getIdAttribute($name, $options); 344 | 345 | $value = (string) $this->getValueAttribute($name, $value); 346 | 347 | unset($options['size']); 348 | 349 | // Next we will convert the attributes into a string form. Also we have removed 350 | // the size attribute, as it was merely a short-cut for the rows and cols on 351 | // the element. Then we'll create the final textarea elements HTML for us. 352 | $options = $this->html->attributes($options); 353 | 354 | return ''.e($value).''; 355 | } 356 | 357 | /** 358 | * Set the text area size on the attributes. 359 | * 360 | * @param array $options 361 | * @return array 362 | */ 363 | protected function setTextAreaSize($options) 364 | { 365 | if (isset($options['size'])) 366 | { 367 | return $this->setQuickTextAreaSize($options); 368 | } 369 | 370 | // If the "size" attribute was not specified, we will just look for the regular 371 | // columns and rows attributes, using sane defaults if these do not exist on 372 | // the attributes array. We'll then return this entire options array back. 373 | $cols = array_get($options, 'cols', 50); 374 | 375 | $rows = array_get($options, 'rows', 10); 376 | 377 | return array_merge($options, compact('cols', 'rows')); 378 | } 379 | 380 | /** 381 | * Set the text area size using the quick "size" attribute. 382 | * 383 | * @param array $options 384 | * @return array 385 | */ 386 | protected function setQuickTextAreaSize($options) 387 | { 388 | $segments = explode('x', $options['size']); 389 | 390 | return array_merge($options, array('cols' => $segments[0], 'rows' => $segments[1])); 391 | } 392 | 393 | /** 394 | * Create a select box field. 395 | * 396 | * @param string $name 397 | * @param array $list 398 | * @param string $selected 399 | * @param array $options 400 | * @return string 401 | */ 402 | public function select($name, $list = array(), $selected = null, $options = array()) 403 | { 404 | // When building a select box the "value" attribute is really the selected one 405 | // so we will use that when checking the model or session for a value which 406 | // should provide a convenient method of re-populating the forms on post. 407 | $selected = $this->getValueAttribute($name, $selected); 408 | 409 | $options['id'] = $this->getIdAttribute($name, $options); 410 | 411 | if ( ! isset($options['name'])) $options['name'] = $name; 412 | 413 | // We will simply loop through the options and build an HTML value for each of 414 | // them until we have an array of HTML declarations. Then we will join them 415 | // all together into one single HTML element that can be put on the form. 416 | $html = array(); 417 | 418 | foreach ($list as $value => $display) 419 | { 420 | $html[] = $this->getSelectOption($display, $value, $selected); 421 | } 422 | 423 | // Once we have all of this HTML, we can join this into a single element after 424 | // formatting the attributes into an HTML "attributes" string, then we will 425 | // build out a final select statement, which will contain all the values. 426 | $options = $this->html->attributes($options); 427 | 428 | $list = implode('', $html); 429 | 430 | return "{$list}"; 431 | } 432 | 433 | /** 434 | * Create a select range field. 435 | * 436 | * @param string $name 437 | * @param string $begin 438 | * @param string $end 439 | * @param string $selected 440 | * @param array $options 441 | * @return string 442 | */ 443 | public function selectRange($name, $begin, $end, $selected = null, $options = array()) 444 | { 445 | $range = array_combine($range = range($begin, $end), $range); 446 | 447 | return $this->select($name, $range, $selected, $options); 448 | } 449 | 450 | /** 451 | * Create a select year field. 452 | * 453 | * @param string $name 454 | * @param string $begin 455 | * @param string $end 456 | * @param string $selected 457 | * @param array $options 458 | * @return string 459 | */ 460 | public function selectYear() 461 | { 462 | return call_user_func_array(array($this, 'selectRange'), func_get_args()); 463 | } 464 | 465 | /** 466 | * Create a select month field. 467 | * 468 | * @param string $name 469 | * @param string $selected 470 | * @param array $options 471 | * @param string $format 472 | * @return string 473 | */ 474 | public function selectMonth($name, $selected = null, $options = array(), $format = '%B') 475 | { 476 | $months = array(); 477 | 478 | foreach (range(1, 12) as $month) 479 | { 480 | $months[$month] = strftime($format, mktime(0, 0, 0, $month, 1)); 481 | } 482 | 483 | return $this->select($name, $months, $selected, $options); 484 | } 485 | 486 | /** 487 | * Get the select option for the given value. 488 | * 489 | * @param string $display 490 | * @param string $value 491 | * @param string $selected 492 | * @return string 493 | */ 494 | public function getSelectOption($display, $value, $selected) 495 | { 496 | if (is_array($display)) 497 | { 498 | return $this->optionGroup($display, $value, $selected); 499 | } 500 | 501 | return $this->option($display, $value, $selected); 502 | } 503 | 504 | /** 505 | * Create an option group form element. 506 | * 507 | * @param array $list 508 | * @param string $label 509 | * @param string $selected 510 | * @return string 511 | */ 512 | protected function optionGroup($list, $label, $selected) 513 | { 514 | $html = array(); 515 | 516 | foreach ($list as $value => $display) 517 | { 518 | $html[] = $this->option($display, $value, $selected); 519 | } 520 | 521 | return ''.implode('', $html).''; 522 | } 523 | 524 | /** 525 | * Create a select element option. 526 | * 527 | * @param string $display 528 | * @param string $value 529 | * @param string $selected 530 | * @return string 531 | */ 532 | protected function option($display, $value, $selected) 533 | { 534 | $selected = $this->getSelectedValue($value, $selected); 535 | 536 | $options = array('value' => e($value), 'selected' => $selected); 537 | 538 | return 'html->attributes($options).'>'.e($display).''; 539 | } 540 | 541 | /** 542 | * Determine if the value is selected. 543 | * 544 | * @param string $value 545 | * @param string $selected 546 | * @return string 547 | */ 548 | protected function getSelectedValue($value, $selected) 549 | { 550 | if (is_array($selected)) 551 | { 552 | return in_array($value, $selected) ? 'selected' : null; 553 | } 554 | 555 | return ((string) $value == (string) $selected) ? 'selected' : null; 556 | } 557 | 558 | /** 559 | * Create a checkbox input field. 560 | * 561 | * @param string $name 562 | * @param mixed $value 563 | * @param bool $checked 564 | * @param array $options 565 | * @return string 566 | */ 567 | public function checkbox($name, $value = 1, $checked = null, $options = array()) 568 | { 569 | return $this->checkable('checkbox', $name, $value, $checked, $options); 570 | } 571 | 572 | /** 573 | * Create a radio button input field. 574 | * 575 | * @param string $name 576 | * @param mixed $value 577 | * @param bool $checked 578 | * @param array $options 579 | * @return string 580 | */ 581 | public function radio($name, $value = null, $checked = null, $options = array()) 582 | { 583 | if (is_null($value)) $value = $name; 584 | 585 | return $this->checkable('radio', $name, $value, $checked, $options); 586 | } 587 | 588 | /** 589 | * Create a checkable input field. 590 | * 591 | * @param string $type 592 | * @param string $name 593 | * @param mixed $value 594 | * @param bool $checked 595 | * @param array $options 596 | * @return string 597 | */ 598 | protected function checkable($type, $name, $value, $checked, $options) 599 | { 600 | $checked = $this->getCheckedState($type, $name, $value, $checked); 601 | 602 | if ($checked) $options['checked'] = 'checked'; 603 | 604 | return $this->input($type, $name, $value, $options); 605 | } 606 | 607 | /** 608 | * Get the check state for a checkable input. 609 | * 610 | * @param string $type 611 | * @param string $name 612 | * @param mixed $value 613 | * @param bool $checked 614 | * @return bool 615 | */ 616 | protected function getCheckedState($type, $name, $value, $checked) 617 | { 618 | switch ($type) 619 | { 620 | case 'checkbox': 621 | return $this->getCheckboxCheckedState($name, $value, $checked); 622 | 623 | case 'radio': 624 | return $this->getRadioCheckedState($name, $value, $checked); 625 | 626 | default: 627 | return $this->getValueAttribute($name) == $value; 628 | } 629 | } 630 | 631 | /** 632 | * Get the check state for a checkbox input. 633 | * 634 | * @param string $name 635 | * @param mixed $value 636 | * @param bool $checked 637 | * @return bool 638 | */ 639 | protected function getCheckboxCheckedState($name, $value, $checked) 640 | { 641 | if (isset($this->session) && ! $this->oldInputIsEmpty() && is_null($this->old($name))) return false; 642 | 643 | if ($this->missingOldAndModel($name)) return $checked; 644 | 645 | $posted = $this->getValueAttribute($name); 646 | 647 | return is_array($posted) ? in_array($value, $posted) : (bool) $posted; 648 | } 649 | 650 | /** 651 | * Get the check state for a radio input. 652 | * 653 | * @param string $name 654 | * @param mixed $value 655 | * @param bool $checked 656 | * @return bool 657 | */ 658 | protected function getRadioCheckedState($name, $value, $checked) 659 | { 660 | if ($this->missingOldAndModel($name)) return $checked; 661 | 662 | return $this->getValueAttribute($name) == $value; 663 | } 664 | 665 | /** 666 | * Determine if old input or model input exists for a key. 667 | * 668 | * @param string $name 669 | * @return bool 670 | */ 671 | protected function missingOldAndModel($name) 672 | { 673 | return (is_null($this->old($name)) && is_null($this->getModelValueAttribute($name))); 674 | } 675 | 676 | /** 677 | * Create a HTML reset input element. 678 | * 679 | * @param string $value 680 | * @param array $attributes 681 | * @return string 682 | */ 683 | public function reset($value, $attributes = array()) 684 | { 685 | return $this->input('reset', null, $value, $attributes); 686 | } 687 | 688 | /** 689 | * Create a HTML image input element. 690 | * 691 | * @param string $url 692 | * @param string $name 693 | * @param array $attributes 694 | * @return string 695 | */ 696 | public function image($url, $name = null, $attributes = array()) 697 | { 698 | $attributes['src'] = $this->url->asset($url); 699 | 700 | return $this->input('image', $name, null, $attributes); 701 | } 702 | 703 | /** 704 | * Create a submit button element. 705 | * 706 | * @param string $value 707 | * @param array $options 708 | * @return string 709 | */ 710 | public function submit($value = null, $options = array()) 711 | { 712 | return $this->input('submit', null, $value, $options); 713 | } 714 | 715 | /** 716 | * Create a button element. 717 | * 718 | * @param string $value 719 | * @param array $options 720 | * @return string 721 | */ 722 | public function button($value = null, $options = array()) 723 | { 724 | if ( ! array_key_exists('type', $options)) 725 | { 726 | $options['type'] = 'button'; 727 | } 728 | 729 | return 'html->attributes($options).'>'.$value.''; 730 | } 731 | 732 | /** 733 | * Parse the form action method. 734 | * 735 | * @param string $method 736 | * @return string 737 | */ 738 | protected function getMethod($method) 739 | { 740 | $method = strtoupper($method); 741 | 742 | return $method != 'GET' ? 'POST' : $method; 743 | } 744 | 745 | /** 746 | * Get the form action from the options. 747 | * 748 | * @param array $options 749 | * @return string 750 | */ 751 | protected function getAction(array $options) 752 | { 753 | // We will also check for a "route" or "action" parameter on the array so that 754 | // developers can easily specify a route or controller action when creating 755 | // a form providing a convenient interface for creating the form actions. 756 | if (isset($options['url'])) 757 | { 758 | return $this->getUrlAction($options['url']); 759 | } 760 | 761 | if (isset($options['route'])) 762 | { 763 | return $this->getRouteAction($options['route']); 764 | } 765 | 766 | // If an action is available, we are attempting to open a form to a controller 767 | // action route. So, we will use the URL generator to get the path to these 768 | // actions and return them from the method. Otherwise, we'll use current. 769 | elseif (isset($options['action'])) 770 | { 771 | return $this->getControllerAction($options['action']); 772 | } 773 | 774 | return $this->url->current(); 775 | } 776 | 777 | /** 778 | * Get the action for a "url" option. 779 | * 780 | * @param array|string $options 781 | * @return string 782 | */ 783 | protected function getUrlAction($options) 784 | { 785 | if (is_array($options)) 786 | { 787 | return $this->url->to($options[0], array_slice($options, 1)); 788 | } 789 | 790 | return $this->url->to($options); 791 | } 792 | 793 | /** 794 | * Get the action for a "route" option. 795 | * 796 | * @param array|string $options 797 | * @return string 798 | */ 799 | protected function getRouteAction($options) 800 | { 801 | if (is_array($options)) 802 | { 803 | return $this->url->route($options[0], array_slice($options, 1)); 804 | } 805 | 806 | return $this->url->route($options); 807 | } 808 | 809 | /** 810 | * Get the action for an "action" option. 811 | * 812 | * @param array|string $options 813 | * @return string 814 | */ 815 | protected function getControllerAction($options) 816 | { 817 | if (is_array($options)) 818 | { 819 | return $this->url->action($options[0], array_slice($options, 1)); 820 | } 821 | 822 | return $this->url->action($options); 823 | } 824 | 825 | /** 826 | * Get the form appendage for the given method. 827 | * 828 | * @param string $method 829 | * @return string 830 | */ 831 | protected function getAppendage($method) 832 | { 833 | list($method, $appendage) = array(strtoupper($method), ''); 834 | 835 | // If the HTTP method is in this list of spoofed methods, we will attach the 836 | // method spoofer hidden input to the form. This allows us to use regular 837 | // form to initiate PUT and DELETE requests in addition to the typical. 838 | if (in_array($method, $this->spoofedMethods)) 839 | { 840 | $appendage .= $this->hidden('_method', $method); 841 | } 842 | 843 | // If the method is something other than GET we will go ahead and attach the 844 | // CSRF token to the form, as this can't hurt and is convenient to simply 845 | // always have available on every form the developers creates for them. 846 | if ($method != 'GET') 847 | { 848 | $appendage .= $this->token(); 849 | } 850 | 851 | return $appendage; 852 | } 853 | 854 | /** 855 | * Get the ID attribute for a field name. 856 | * 857 | * @param string $name 858 | * @param array $attributes 859 | * @return string 860 | */ 861 | public function getIdAttribute($name, $attributes) 862 | { 863 | if (array_key_exists('id', $attributes)) 864 | { 865 | return $attributes['id']; 866 | } 867 | 868 | if (in_array($name, $this->labels)) 869 | { 870 | return $name; 871 | } 872 | } 873 | 874 | /** 875 | * Get the value that should be assigned to the field. 876 | * 877 | * @param string $name 878 | * @param string $value 879 | * @return string 880 | */ 881 | public function getValueAttribute($name, $value = null) 882 | { 883 | if (is_null($name)) return $value; 884 | 885 | if ( ! is_null($this->old($name))) 886 | { 887 | return $this->old($name); 888 | } 889 | 890 | if ( ! is_null($value)) return $value; 891 | 892 | if (isset($this->model)) 893 | { 894 | return $this->getModelValueAttribute($name); 895 | } 896 | } 897 | 898 | /** 899 | * Get the model value that should be assigned to the field. 900 | * 901 | * @param string $name 902 | * @return string 903 | */ 904 | protected function getModelValueAttribute($name) 905 | { 906 | if (is_object($this->model)) 907 | { 908 | return object_get($this->model, $this->transformKey($name)); 909 | } 910 | elseif (is_array($this->model)) 911 | { 912 | return array_get($this->model, $this->transformKey($name)); 913 | } 914 | } 915 | 916 | /** 917 | * Get a value from the session's old input. 918 | * 919 | * @param string $name 920 | * @return string 921 | */ 922 | public function old($name) 923 | { 924 | if (isset($this->session)) 925 | { 926 | return $this->session->getOldInput($this->transformKey($name)); 927 | } 928 | } 929 | 930 | /** 931 | * Determine if the old input is empty. 932 | * 933 | * @return bool 934 | */ 935 | public function oldInputIsEmpty() 936 | { 937 | return (isset($this->session) && count($this->session->getOldInput()) == 0); 938 | } 939 | 940 | /** 941 | * Transform key from array to dot syntax. 942 | * 943 | * @param string $key 944 | * @return string 945 | */ 946 | protected function transformKey($key) 947 | { 948 | return str_replace(array('.', '[]', '[', ']'), array('_', '', '.', ''), $key); 949 | } 950 | 951 | /** 952 | * Get the session store implementation. 953 | * 954 | * @return \Illuminate\Session\Store $session 955 | */ 956 | public function getSessionStore() 957 | { 958 | return $this->session; 959 | } 960 | 961 | /** 962 | * Set the session store implementation. 963 | * 964 | * @param \Illuminate\Session\Store $session 965 | * @return $this 966 | */ 967 | public function setSessionStore(Session $session) 968 | { 969 | $this->session = $session; 970 | 971 | return $this; 972 | } 973 | 974 | } 975 | --------------------------------------------------------------------------------