Field.php 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268
  1. <?php
  2. namespace Dcat\Admin\Form;
  3. use Dcat\Admin\Admin;
  4. use Dcat\Admin\Form;
  5. use Dcat\Admin\Support\Helper;
  6. use Dcat\Admin\Traits\HasBuilderEvents;
  7. use Dcat\Admin\Widgets\Form as WidgetForm;
  8. use Illuminate\Contracts\Support\Arrayable;
  9. use Illuminate\Contracts\Support\Renderable;
  10. use Illuminate\Support\Arr;
  11. use Illuminate\Support\Fluent;
  12. use Illuminate\Support\Str;
  13. use Illuminate\Support\Traits\Macroable;
  14. /**
  15. * Class Field.
  16. */
  17. class Field implements Renderable
  18. {
  19. use Macroable,
  20. Form\Concerns\HasFieldValidator,
  21. HasBuilderEvents;
  22. const FILE_DELETE_FLAG = '_file_del_';
  23. const FIELD_CLASS_PREFIX = 'field_';
  24. /**
  25. * Element id.
  26. *
  27. * @var array|string
  28. */
  29. protected $id;
  30. /**
  31. * Element value.
  32. *
  33. * @var mixed
  34. */
  35. protected $value;
  36. /**
  37. * Data of all original columns of value.
  38. *
  39. * @var mixed
  40. */
  41. protected $data;
  42. /**
  43. * Field original value.
  44. *
  45. * @var mixed
  46. */
  47. protected $original;
  48. /**
  49. * Field default value.
  50. *
  51. * @var mixed
  52. */
  53. protected $default;
  54. /**
  55. * Element label.
  56. *
  57. * @var string
  58. */
  59. protected $label = '';
  60. /**
  61. * Column name.
  62. *
  63. * @var string|array
  64. */
  65. protected $column = '';
  66. /**
  67. * Form element name.
  68. *
  69. * @var string|array
  70. */
  71. protected $elementName = [];
  72. /**
  73. * Form element classes.
  74. *
  75. * @var array
  76. */
  77. protected $elementClass = [];
  78. /**
  79. * Variables of elements.
  80. *
  81. * @var array
  82. */
  83. protected $variables = [];
  84. /**
  85. * Options for specify elements.
  86. *
  87. * @var array
  88. */
  89. protected $options = [];
  90. /**
  91. * Checked for specify elements.
  92. *
  93. * @var array
  94. */
  95. protected $checked = [];
  96. /**
  97. * Css required by this field.
  98. *
  99. * @var array
  100. */
  101. protected static $css = [];
  102. /**
  103. * Js required by this field.
  104. *
  105. * @var array
  106. */
  107. protected static $js = [];
  108. /**
  109. * Script for field.
  110. *
  111. * @var string
  112. */
  113. protected $script = '';
  114. /**
  115. * Element attributes.
  116. *
  117. * @var array
  118. */
  119. protected $attributes = [];
  120. /**
  121. * Parent form.
  122. *
  123. * @var Form|WidgetForm
  124. */
  125. protected $form = null;
  126. /**
  127. * View for field to render.
  128. *
  129. * @var string
  130. */
  131. protected $view = '';
  132. /**
  133. * Help block.
  134. *
  135. * @var array
  136. */
  137. protected $help = [];
  138. /**
  139. * Key for errors.
  140. *
  141. * @var string|array
  142. */
  143. protected $errorKey;
  144. /**
  145. * Placeholder for this field.
  146. *
  147. * @var string|array
  148. */
  149. protected $placeholder;
  150. /**
  151. * Width for label and field.
  152. *
  153. * @var array
  154. */
  155. protected $width = [
  156. 'label' => 2,
  157. 'field' => 8,
  158. ];
  159. /**
  160. * If the form horizontal layout.
  161. *
  162. * @var bool
  163. */
  164. protected $horizontal = true;
  165. /**
  166. * column data format.
  167. *
  168. * @var \Closure
  169. */
  170. protected $customFormat = null;
  171. /**
  172. * @var bool
  173. */
  174. protected $display = true;
  175. /**
  176. * @var array
  177. */
  178. protected $labelClass = [];
  179. /**
  180. * @var \Closure[]
  181. */
  182. protected $savingCallbacks = [];
  183. /**
  184. * Field constructor.
  185. *
  186. * @param string|array $column
  187. * @param array $arguments
  188. */
  189. public function __construct($column, $arguments = [])
  190. {
  191. $this->column = $column;
  192. $this->label = $this->formatLabel($arguments);
  193. $this->id = $this->formatId($column);
  194. $this->callResolving();
  195. }
  196. /**
  197. * Get the field element id.
  198. *
  199. * @return string|array
  200. */
  201. public function getElementId()
  202. {
  203. return $this->id;
  204. }
  205. /**
  206. * Format the field element id.
  207. *
  208. * @param string|array $column
  209. *
  210. * @return string|array
  211. */
  212. protected function formatId($column)
  213. {
  214. $random = Str::random(5);
  215. if (is_array($column)) {
  216. $id = [];
  217. foreach (str_replace('.', '-', $column) as $k => $v) {
  218. $id[$k] = "{$v}-{$random}";
  219. }
  220. return $id;
  221. }
  222. return 'form-field-'.str_replace('.', '-', $column).'-'.$random;
  223. }
  224. /**
  225. * @param string|null $relationName
  226. * @param string $relationPrimaryKey
  227. *
  228. * @return $this
  229. */
  230. public function setNestedFormRelation(?string $relationName, $relationPrimaryKey)
  231. {
  232. if (is_array($this->id)) {
  233. $this->id = array_map(function ($v) {
  234. return $v.NestedForm::DEFAULT_KEY_NAME;
  235. }, $this->id);
  236. } else {
  237. $this->id .= NestedForm::DEFAULT_KEY_NAME;
  238. }
  239. return $this;
  240. }
  241. /**
  242. * Format the label value.
  243. *
  244. * @param array $arguments
  245. *
  246. * @return string
  247. */
  248. protected function formatLabel($arguments = [])
  249. {
  250. $column = is_array($this->column) ? current($this->column) : $this->column;
  251. $label = isset($arguments[0]) ? $arguments[0] : admin_trans_field($column);
  252. return str_replace(['.', '_'], ' ', $label);
  253. }
  254. /**
  255. * Format the name of the field.
  256. *
  257. * @param string $column
  258. *
  259. * @return array|mixed|string
  260. */
  261. protected function formatName($column)
  262. {
  263. if (is_string($column)) {
  264. $name = explode('.', $column);
  265. if (count($name) == 1) {
  266. return $name[0];
  267. }
  268. $html = array_shift($name);
  269. foreach ($name as $piece) {
  270. $html .= "[$piece]";
  271. }
  272. return $html;
  273. }
  274. if (is_array($this->column)) {
  275. $names = [];
  276. foreach ($this->column as $key => $name) {
  277. $names[$key] = $this->formatName($name);
  278. }
  279. return $names;
  280. }
  281. return '';
  282. }
  283. /**
  284. * Set form element name.
  285. *
  286. * @param string|array $name
  287. *
  288. * @return $this
  289. *
  290. * @author Edwin Hui
  291. */
  292. public function setElementName($name)
  293. {
  294. $this->elementName = $name;
  295. return $this;
  296. }
  297. /**
  298. * Get form element name.
  299. *
  300. * @return array|mixed|string
  301. */
  302. public function getElementName()
  303. {
  304. return $this->elementName ?: $this->formatName($this->column);
  305. }
  306. /**
  307. * Fill data to the field.
  308. *
  309. * @param array $data
  310. *
  311. * @return void
  312. */
  313. final public function fill($data)
  314. {
  315. $data = Helper::array($data);
  316. $this->data($data);
  317. $this->value = $this->formatFieldData($data);
  318. $this->callCustomFormatter();
  319. }
  320. /**
  321. * Format field data.
  322. *
  323. * @param array $data
  324. *
  325. * @return mixed
  326. */
  327. protected function formatFieldData($data)
  328. {
  329. if (is_array($this->column)) {
  330. $value = [];
  331. foreach ($this->column as $key => $column) {
  332. $value[$key] = Arr::get($data, $column);
  333. }
  334. return $value;
  335. }
  336. return Arr::get($data, $this->column, $this->value);
  337. }
  338. /**
  339. * custom format form column data when edit.
  340. *
  341. * @param \Closure $call
  342. *
  343. * @return $this
  344. */
  345. public function customFormat(\Closure $call)
  346. {
  347. $this->customFormat = $call;
  348. return $this;
  349. }
  350. /**
  351. * Set original value to the field.
  352. *
  353. * @param array $data
  354. *
  355. * @return void
  356. */
  357. final public function setOriginal($data)
  358. {
  359. $data = Helper::array($data);
  360. $this->original = $this->formatFieldData($data);
  361. $this->callCustomFormatter('original', new Fluent($data));
  362. }
  363. /**
  364. * @param string $key
  365. * @param Fluent|null $dataremoveField
  366. */
  367. protected function callCustomFormatter($key = 'value', Fluent $data = null)
  368. {
  369. if ($this->customFormat) {
  370. $this->{$key} = $this->customFormat
  371. ->call(
  372. $data ?: $this->data(),
  373. $this->{$key},
  374. $this->column,
  375. $this
  376. );
  377. }
  378. }
  379. /**
  380. * @param Form|WidgetForm $form
  381. *
  382. * @return $this
  383. */
  384. public function setForm($form = null)
  385. {
  386. $this->form = $form;
  387. return $this;
  388. }
  389. /**
  390. * @return Fluent
  391. */
  392. public function values()
  393. {
  394. return $this->form ? $this->form->model() : new Fluent();
  395. }
  396. /**
  397. * Set width for field and label.
  398. *
  399. * @param int $field
  400. * @param int $label
  401. *
  402. * @return $this
  403. */
  404. public function width($field = 8, $label = 2)
  405. {
  406. $this->width = [
  407. 'label' => $label,
  408. 'field' => $field,
  409. ];
  410. return $this;
  411. }
  412. /**
  413. * Set the field options.
  414. *
  415. * @param array $options
  416. *
  417. * @return $this
  418. */
  419. public function options($options = [])
  420. {
  421. if ($options instanceof Arrayable) {
  422. $options = $options->toArray();
  423. }
  424. if (is_array($this->options)) {
  425. $this->options = array_merge($this->options, $options);
  426. } else {
  427. $this->options = $options;
  428. }
  429. return $this;
  430. }
  431. /**
  432. * Set the field option checked.
  433. *
  434. * @param array $checked
  435. *
  436. * @return $this
  437. */
  438. public function checked($checked = [])
  439. {
  440. if ($checked instanceof Arrayable) {
  441. $checked = $checked->toArray();
  442. }
  443. $this->checked = array_merge($this->checked, (array) $checked);
  444. return $this;
  445. }
  446. /**
  447. * Set key for error message.
  448. *
  449. * @param string|array $key
  450. *
  451. * @return $this
  452. */
  453. public function setErrorKey($key)
  454. {
  455. $this->errorKey = $key;
  456. return $this;
  457. }
  458. /**
  459. * Get key for error message.
  460. *
  461. * @return string
  462. */
  463. public function getErrorKey()
  464. {
  465. return $this->errorKey ?: $this->column;
  466. }
  467. /**
  468. * Set or get value of the field.
  469. *
  470. * @param null $value
  471. *
  472. * @return mixed
  473. */
  474. public function value($value = null)
  475. {
  476. if (is_null($value)) {
  477. if (
  478. $this->value === null
  479. || (is_array($this->value) && empty($this->value))
  480. ) {
  481. return $this->default();
  482. }
  483. return $this->value;
  484. }
  485. $this->value = $value;
  486. return $this;
  487. }
  488. /**
  489. * Set or get data.
  490. *
  491. * @param array $data
  492. *
  493. * @return $this|Fluent
  494. */
  495. public function data(array $data = null)
  496. {
  497. if (is_null($data)) {
  498. if (! $this->data || is_array($this->data)) {
  499. $this->data = new Fluent((array) $this->data);
  500. }
  501. return $this->data;
  502. }
  503. $this->data = new Fluent($data);
  504. return $this;
  505. }
  506. /**
  507. * Get or set default value for field.
  508. *
  509. * @param $default
  510. *
  511. * @return $this|mixed
  512. */
  513. public function default($default = null)
  514. {
  515. if ($default === null) {
  516. if (
  517. $this->form
  518. && method_exists($this->form, 'isCreating')
  519. && ! $this->form->isCreating()
  520. ) {
  521. return;
  522. }
  523. if ($this->default instanceof \Closure) {
  524. return call_user_func($this->default, $this->form);
  525. }
  526. return $this->default;
  527. }
  528. $this->default = $default;
  529. return $this;
  530. }
  531. /**
  532. * Set help block for current field.
  533. *
  534. * @param string $text
  535. * @param string $icon
  536. *
  537. * @return $this
  538. */
  539. public function help($text = '', $icon = 'feather icon-help-circle')
  540. {
  541. $this->help = compact('text', 'icon');
  542. return $this;
  543. }
  544. /**
  545. * Get column of the field.
  546. *
  547. * @return string|array
  548. */
  549. public function column()
  550. {
  551. return $this->column;
  552. }
  553. /**
  554. * Get or set label of the field.
  555. *
  556. * @param null $label
  557. *
  558. * @return $this|string
  559. */
  560. public function label($label = null)
  561. {
  562. if ($label == null) {
  563. return $this->label;
  564. }
  565. if ($label instanceof \Closure) {
  566. $label = $label($this->label);
  567. }
  568. $this->label = $label;
  569. return $this;
  570. }
  571. /**
  572. * @return mixed
  573. */
  574. public function old()
  575. {
  576. return old($this->column, $this->value());
  577. }
  578. /**
  579. * Get original value of the field.
  580. *
  581. * @return mixed
  582. */
  583. public function original()
  584. {
  585. return $this->original;
  586. }
  587. /**
  588. * Sanitize input data.
  589. *
  590. * @param array $input
  591. * @param string $column
  592. *
  593. * @return array
  594. */
  595. protected function sanitizeInput($input, $column)
  596. {
  597. if ($this instanceof Field\MultipleSelect) {
  598. $value = Arr::get($input, $column);
  599. Arr::set($input, $column, array_filter($value));
  600. }
  601. return $input;
  602. }
  603. /**
  604. * Add html attributes to elements.
  605. *
  606. * @param array|string $attribute
  607. * @param mixed $value
  608. *
  609. * @return $this
  610. */
  611. public function attribute($attribute, $value = null)
  612. {
  613. if (is_array($attribute)) {
  614. $this->attributes = array_merge($this->attributes, $attribute);
  615. } else {
  616. $this->attributes[$attribute] = (string) $value;
  617. }
  618. return $this;
  619. }
  620. /**
  621. * @param string $key
  622. *
  623. * @return bool
  624. */
  625. public function hasAttribute(string $key)
  626. {
  627. return array_key_exists($key, $this->attributes);
  628. }
  629. /**
  630. * @param string $key
  631. *
  632. * @return mixed|null
  633. */
  634. public function getAttribute(string $key)
  635. {
  636. return $this->attributes[$key] ?? null;
  637. }
  638. /**
  639. * Specifies a regular expression against which to validate the value of the input.
  640. *
  641. * @param string $error
  642. * @param string $regexp
  643. *
  644. * @return $this
  645. */
  646. public function pattern($regexp, $error = null)
  647. {
  648. if ($error) {
  649. $this->attribute('data-pattern-error', $error);
  650. }
  651. return $this->attribute('pattern', $regexp);
  652. }
  653. /**
  654. * set the input filed required.
  655. *
  656. * @param bool $isLabelAsterisked
  657. *
  658. * @return $this
  659. */
  660. public function required($isLabelAsterisked = true)
  661. {
  662. if ($isLabelAsterisked) {
  663. $this->setLabelClass(['asterisk']);
  664. }
  665. $this->rules('required');
  666. return $this->attribute('required', true);
  667. }
  668. /**
  669. * Set the field automatically get focus.
  670. *
  671. * @return $this
  672. */
  673. public function autofocus()
  674. {
  675. return $this->attribute('autofocus', true);
  676. }
  677. /**
  678. * Set the field as readonly mode.
  679. *
  680. * @return $this
  681. */
  682. public function readOnly()
  683. {
  684. return $this->attribute('readonly', true);
  685. }
  686. /**
  687. * Set field as disabled.
  688. *
  689. * @return $this
  690. */
  691. public function disable()
  692. {
  693. return $this->attribute('disabled', true);
  694. }
  695. /**
  696. * Get or set field placeholder.
  697. *
  698. * @param string $placeholder
  699. *
  700. * @return $this|string
  701. */
  702. public function placeholder($placeholder = null)
  703. {
  704. if ($placeholder === null) {
  705. return $this->placeholder ?: trans('admin.input').' '.$this->label;
  706. }
  707. $this->placeholder = $placeholder;
  708. return $this;
  709. }
  710. /**
  711. * @param mixed $value
  712. *
  713. * @return mixed
  714. */
  715. protected function prepareInputValue($value)
  716. {
  717. return $value;
  718. }
  719. /**
  720. * @param \Closure $closure
  721. *
  722. * @return $this
  723. */
  724. public function saving(\Closure $closure)
  725. {
  726. $this->savingCallbacks[] = $closure;
  727. return $this;
  728. }
  729. /**
  730. * Prepare for a field value before update or insert.
  731. *
  732. * @param mixed $value
  733. *
  734. * @return mixed
  735. */
  736. final public function prepare($value)
  737. {
  738. $value = $this->prepareInputValue($value);
  739. if ($this->savingCallbacks) {
  740. foreach ($this->savingCallbacks as $callback) {
  741. $value = $callback->call($this->data());
  742. }
  743. }
  744. return $value;
  745. }
  746. /**
  747. * Format the field attributes.
  748. *
  749. * @return string
  750. */
  751. protected function formatAttributes()
  752. {
  753. $html = [];
  754. foreach ($this->attributes as $name => $value) {
  755. $html[] = $name.'="'.e($value).'"';
  756. }
  757. return implode(' ', $html);
  758. }
  759. /**
  760. * @return $this
  761. */
  762. public function disableHorizontal()
  763. {
  764. $this->horizontal = false;
  765. return $this;
  766. }
  767. /**
  768. * @return array
  769. */
  770. public function getViewElementClasses()
  771. {
  772. if ($this->horizontal) {
  773. return [
  774. 'label' => "col-md-{$this->width['label']} {$this->getLabelClass()} text-capitalize",
  775. 'field' => "col-md-{$this->width['field']}",
  776. 'form-group' => 'form-group row form-field',
  777. ];
  778. }
  779. return ['label' => $this->getLabelClass().' text-capitalize', 'field' => '', 'form-group' => 'form-field'];
  780. }
  781. /**
  782. * Set element class.
  783. *
  784. * @param string|array $class
  785. *
  786. * @return $this
  787. */
  788. public function setElementClass($class)
  789. {
  790. $this->elementClass = array_merge($this->elementClass, (array) $class);
  791. return $this;
  792. }
  793. /**
  794. * Get element class.
  795. *
  796. * @return array
  797. */
  798. public function getElementClass()
  799. {
  800. if (! $this->elementClass) {
  801. $name = $this->getElementName();
  802. $this->elementClass = array_map(function ($v) {
  803. return static::FIELD_CLASS_PREFIX.$v;
  804. }, (array) str_replace(['[', ']'], '_', $name));
  805. }
  806. return $this->elementClass;
  807. }
  808. /**
  809. * Get element class string.
  810. *
  811. * @return mixed
  812. */
  813. public function getElementClassString()
  814. {
  815. $elementClass = $this->getElementClass();
  816. if (Arr::isAssoc($elementClass)) {
  817. $classes = [];
  818. foreach ($elementClass as $index => $class) {
  819. $classes[$index] = is_array($class) ? implode(' ', $class) : $class;
  820. }
  821. return $classes;
  822. }
  823. return implode(' ', $elementClass);
  824. }
  825. /**
  826. * Get element class selector.
  827. *
  828. * @return string|array
  829. */
  830. public function getElementClassSelector()
  831. {
  832. $elementClass = $this->getElementClass();
  833. $formId = $this->getFormElementId();
  834. $formId = $formId ? '#'.$formId : '';
  835. if (Arr::isAssoc($elementClass)) {
  836. $classes = [];
  837. foreach ($elementClass as $index => $class) {
  838. $classes[$index] = $formId.' .'.(is_array($class) ? implode('.', $class) : $class);
  839. }
  840. return $classes;
  841. }
  842. return $formId.' .'.implode('.', $elementClass);
  843. }
  844. /**
  845. * @return $this
  846. */
  847. public function hideInDialog()
  848. {
  849. if (
  850. $this->form instanceof Form
  851. && $this->form->inDialog()
  852. ) {
  853. $this->display(false);
  854. }
  855. return $this;
  856. }
  857. /**
  858. * @return string|null
  859. */
  860. protected function getFormElementId()
  861. {
  862. return $this->form ? $this->form->getElementId() : null;
  863. }
  864. /**
  865. * Add the element class.
  866. *
  867. * @param $class
  868. *
  869. * @return $this
  870. */
  871. public function addElementClass($class)
  872. {
  873. $this->elementClass = array_unique(
  874. array_merge($this->elementClass, (array) $class)
  875. );
  876. return $this;
  877. }
  878. /**
  879. * Remove element class.
  880. *
  881. * @param $class
  882. *
  883. * @return $this
  884. */
  885. public function removeElementClass($class)
  886. {
  887. $delClass = [];
  888. if (is_string($class) || is_array($class)) {
  889. $delClass = (array) $class;
  890. }
  891. foreach ($delClass as $del) {
  892. if (($key = array_search($del, $this->elementClass))) {
  893. unset($this->elementClass[$key]);
  894. }
  895. }
  896. return $this;
  897. }
  898. /**
  899. * Add variables to field view.
  900. *
  901. * @param array $variables
  902. *
  903. * @return $this
  904. */
  905. protected function addVariables(array $variables = [])
  906. {
  907. $this->variables = array_merge($this->variables, $variables);
  908. return $this;
  909. }
  910. /**
  911. * @param array|string $labelClass
  912. * @param bool $append
  913. *
  914. * @return $this|string
  915. */
  916. public function setLabelClass($labelClass, bool $append = true)
  917. {
  918. $this->labelClass = $append
  919. ? array_unique(array_merge($this->labelClass, (array) $labelClass))
  920. : (array) $labelClass;
  921. return $this;
  922. }
  923. /**
  924. * @return string
  925. */
  926. public function getLabelClass()
  927. {
  928. return implode(' ', $this->labelClass);
  929. }
  930. /**
  931. * Get the view variables of this field.
  932. *
  933. * @return array
  934. */
  935. public function variables()
  936. {
  937. return array_merge($this->variables, [
  938. 'id' => $this->id,
  939. 'name' => $this->getElementName(),
  940. 'help' => $this->help,
  941. 'class' => $this->getElementClassString(),
  942. 'value' => $this->value(),
  943. 'label' => $this->label,
  944. 'viewClass' => $this->getViewElementClasses(),
  945. 'column' => $this->column,
  946. 'errorKey' => $this->getErrorKey(),
  947. 'attributes' => $this->formatAttributes(),
  948. 'placeholder' => $this->placeholder(),
  949. 'disabled' => $this->attributes['disabled'] ?? false,
  950. 'formId' => $this->getFormElementId(),
  951. ]);
  952. }
  953. protected function isCreating()
  954. {
  955. return request()->isMethod('POST');
  956. }
  957. protected function isEditing()
  958. {
  959. return request()->isMethod('PUT');
  960. }
  961. /**
  962. * Get view of this field.
  963. *
  964. * @return string
  965. */
  966. public function view()
  967. {
  968. return $this->view ?: 'admin::form.'.strtolower(class_basename(static::class));
  969. }
  970. /**
  971. * Set view of current field.
  972. *
  973. * @return string
  974. */
  975. public function setView($view)
  976. {
  977. $this->view = $view;
  978. return $this;
  979. }
  980. /**
  981. * Get script of current field.
  982. *
  983. * @return string
  984. */
  985. public function getScript()
  986. {
  987. return $this->script;
  988. }
  989. /**
  990. * Set script of current field.
  991. *
  992. * @return self
  993. */
  994. public function script($script)
  995. {
  996. $this->script = $script;
  997. return $this;
  998. }
  999. /**
  1000. * To set this field should render or not.
  1001. *
  1002. * @return self
  1003. */
  1004. public function display(bool $display)
  1005. {
  1006. $this->display = $display;
  1007. return $this;
  1008. }
  1009. /**
  1010. * If this field should render.
  1011. *
  1012. * @return bool
  1013. */
  1014. protected function shouldRender()
  1015. {
  1016. return $this->display;
  1017. }
  1018. public function saveAsJson($option = 0)
  1019. {
  1020. return $this->saving(function ($value) use ($option) {
  1021. if (! $value || is_scalar($value)) {
  1022. return $value;
  1023. }
  1024. return json_encode($value, $option);
  1025. });
  1026. }
  1027. public function saveAsJoin(string $glue = ',')
  1028. {
  1029. return $this->saving(function ($value) use ($glue) {
  1030. if (! $value || is_scalar($value)) {
  1031. return $value;
  1032. }
  1033. return implode($glue, (array) $value);
  1034. });
  1035. }
  1036. public function saveAsString()
  1037. {
  1038. return $this->saving(function ($value) {
  1039. return (string) $value;
  1040. });
  1041. }
  1042. public function saveAsInteger()
  1043. {
  1044. return $this->saving(function ($value) {
  1045. return (int) $value;
  1046. });
  1047. }
  1048. /**
  1049. * Collect assets required by this field.
  1050. */
  1051. public static function collectAssets()
  1052. {
  1053. static::$js && Admin::js(static::$js);
  1054. static::$css && Admin::css(static::$css);
  1055. }
  1056. /**
  1057. * Render this filed.
  1058. *
  1059. * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|string
  1060. */
  1061. public function render()
  1062. {
  1063. if (! $this->shouldRender()) {
  1064. return '';
  1065. }
  1066. $this->callComposing();
  1067. Admin::script($this->script);
  1068. return view($this->view(), $this->variables());
  1069. }
  1070. /**
  1071. * @return string
  1072. */
  1073. public function __toString()
  1074. {
  1075. $view = $this->render();
  1076. return $view instanceof Renderable ? $view->render() : (string) $view;
  1077. }
  1078. }