PageRenderTime 29ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/vendor/laravelcollective/html/src/FormBuilder.php

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