Grid.php 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201
  1. <?php
  2. namespace Dcat\Admin;
  3. use Closure;
  4. use Dcat\Admin\Exception\Handler;
  5. use Dcat\Admin\Grid\Column;
  6. use Dcat\Admin\Grid\Displayers;
  7. use Dcat\Admin\Grid\Exporter;
  8. use Dcat\Admin\Grid\Exporters\AbstractExporter;
  9. use Dcat\Admin\Grid\Filter;
  10. use Dcat\Admin\Grid\Header;
  11. use Dcat\Admin\Grid\Model;
  12. use Dcat\Admin\Grid\Responsive;
  13. use Dcat\Admin\Grid\Row;
  14. use Dcat\Admin\Grid\Tools;
  15. use Dcat\Admin\Grid\Concerns;
  16. use Dcat\Admin\Contracts\Repository;
  17. use Dcat\Admin\Support\Helper;
  18. use Dcat\Admin\Traits\BuilderEvents;
  19. use Illuminate\Support\Traits\Macroable;
  20. use Illuminate\Contracts\Support\Htmlable;
  21. use Illuminate\Contracts\Support\Renderable;
  22. use Illuminate\Support\Collection;
  23. use Illuminate\Support\Facades\Input;
  24. use Illuminate\Support\Facades\URL;
  25. use Illuminate\Support\Str;
  26. use Jenssegers\Mongodb\Eloquent\Model as MongodbModel;
  27. class Grid
  28. {
  29. use BuilderEvents,
  30. Concerns\HasElementNames,
  31. Concerns\Actions,
  32. Concerns\Options,
  33. Concerns\MultipleHeader,
  34. Concerns\QuickSearch,
  35. Macroable {
  36. __call as macroCall;
  37. }
  38. /**
  39. * The grid data model instance.
  40. *
  41. * @var \Dcat\Admin\Grid\Model
  42. */
  43. protected $model;
  44. /**
  45. * Collection of all grid columns.
  46. *
  47. * @var \Illuminate\Support\Collection
  48. */
  49. protected $columns;
  50. /**
  51. * Collection of all data rows.
  52. *
  53. * @var \Illuminate\Support\Collection
  54. */
  55. protected $rows;
  56. /**
  57. * Rows callable fucntion.
  58. *
  59. * @var \Closure[]
  60. */
  61. protected $rowsCallback = [];
  62. /**
  63. * All column names of the grid.
  64. *
  65. * @var array
  66. */
  67. protected $columnNames = [];
  68. /**
  69. * Grid builder.
  70. *
  71. * @var \Closure
  72. */
  73. protected $builder;
  74. /**
  75. * Mark if the grid is built.
  76. *
  77. * @var bool
  78. */
  79. protected $built = false;
  80. /**
  81. * All variables in grid view.
  82. *
  83. * @var array
  84. */
  85. protected $variables = [];
  86. /**
  87. * The grid Filter.
  88. *
  89. * @var \Dcat\Admin\Grid\Filter
  90. */
  91. protected $filter;
  92. /**
  93. * Resource path of the grid.
  94. *
  95. * @var
  96. */
  97. protected $resourcePath;
  98. /**
  99. * Default primary key name.
  100. *
  101. * @var string
  102. */
  103. protected $keyName = 'id';
  104. /**
  105. * Export driver.
  106. *
  107. * @var string
  108. */
  109. protected $exporter;
  110. /**
  111. * View for grid to render.
  112. *
  113. * @var string
  114. */
  115. protected $view = 'admin::grid.table';
  116. /**
  117. * Per-page options.
  118. *
  119. * @var array
  120. */
  121. protected $perPages = [10, 20, 30, 50, 100, 200];
  122. /**
  123. * Default items count per-page.
  124. *
  125. * @var int
  126. */
  127. protected $perPage = 20;
  128. /**
  129. * Header tools.
  130. *
  131. * @var Tools
  132. */
  133. protected $tools;
  134. /**
  135. * @var Closure
  136. */
  137. protected $header;
  138. /**
  139. * @var Closure
  140. */
  141. protected $footer;
  142. /**
  143. * @var Closure
  144. */
  145. protected $wrapper;
  146. /**
  147. * @var Responsive
  148. */
  149. protected $responsive;
  150. /**
  151. * @var bool
  152. */
  153. protected $addNumberColumn = false;
  154. /**
  155. * @var string
  156. */
  157. protected $tableId;
  158. /**
  159. * Create a new grid instance.
  160. *
  161. * @param Repository $model
  162. * @param Closure $builder
  163. */
  164. public function __construct(Repository $repository = null, $builder = null)
  165. {
  166. if ($repository) {
  167. $this->keyName = $repository->getKeyName();
  168. }
  169. $this->model = new Model($repository);
  170. $this->columns = new Collection();
  171. $this->rows = new Collection();
  172. $this->builder = $builder;
  173. $this->tableId = 'grid-'.Str::random(8);
  174. $this->model()->setGrid($this);
  175. $this->setupTools();
  176. $this->setupFilter();
  177. $this->callResolving();
  178. }
  179. /**
  180. * Create a grid instance.
  181. *
  182. * @param mixed ...$params
  183. * @return $this
  184. */
  185. public static function make(...$params)
  186. {
  187. return new static(...$params);
  188. }
  189. /**
  190. * Enable responsive tables.
  191. * @see https://github.com/nadangergeo/RWD-Table-Patterns
  192. *
  193. * @return Responsive
  194. */
  195. public function responsive()
  196. {
  197. if (!$this->responsive) {
  198. $this->responsive = new Responsive($this);
  199. }
  200. return $this->responsive;
  201. }
  202. /**
  203. * @return string
  204. */
  205. public function getTableId()
  206. {
  207. return $this->tableId;
  208. }
  209. /**
  210. * @return bool
  211. */
  212. public function allowResponsive()
  213. {
  214. return $this->responsive ? true : false;
  215. }
  216. /**
  217. * @return bool
  218. */
  219. public function allowHeader()
  220. {
  221. if (
  222. $this->option('show_toolbar')
  223. && (
  224. $this->getTools()->has() ||
  225. $this->allowExportBtn() ||
  226. $this->allowCreateBtn() ||
  227. $this->allowQuickCreateBtn() ||
  228. $this->allowResponsive() ||
  229. !empty($this->variables['title'])
  230. )
  231. ) {
  232. return true;
  233. }
  234. return false;
  235. }
  236. /**
  237. * Setup grid tools.
  238. */
  239. public function setupTools()
  240. {
  241. $this->tools = new Tools($this);
  242. }
  243. /**
  244. * Setup grid filter.
  245. *
  246. * @return void
  247. */
  248. protected function setupFilter()
  249. {
  250. $this->filter = new Filter($this->model());
  251. }
  252. /**
  253. * Handle export request.
  254. *
  255. * @param bool $forceExport
  256. */
  257. protected function handleExportRequest($forceExport = false)
  258. {
  259. if (!$scope = request(Exporter::$queryName)) {
  260. return;
  261. }
  262. // clear output buffer.
  263. if (ob_get_length()) {
  264. ob_end_clean();
  265. }
  266. $this->model()->usePaginate(false);
  267. if ($this->builder) {
  268. call_user_func($this->builder, $this);
  269. $this->getExporter($scope)->export();
  270. }
  271. if ($forceExport) {
  272. $this->getExporter($scope)->export();
  273. }
  274. }
  275. /**
  276. * @param string $scope
  277. *
  278. * @return AbstractExporter
  279. */
  280. protected function getExporter($scope)
  281. {
  282. return (new Exporter($this))->resolve($this->exporter)->withScope($scope);
  283. }
  284. /**
  285. * Get primary key name of model.
  286. *
  287. * @return string
  288. */
  289. public function getKeyName()
  290. {
  291. return $this->keyName ?: 'id';
  292. }
  293. /**
  294. * Set primary key name.
  295. *
  296. * @param string $name
  297. */
  298. public function setKeyName(string $name)
  299. {
  300. $this->keyName = $name;
  301. }
  302. /**
  303. * Add column to Grid.
  304. *
  305. * @param string $name
  306. * @param string $label
  307. *
  308. * @return Column|Collection
  309. */
  310. public function column($name, $label = '')
  311. {
  312. if (strpos($name, '.') !== false) {
  313. list($relationName, $relationColumn) = explode('.', $name);
  314. $label = empty($label) ? admin_trans_field($relationColumn) : $label;
  315. $name = Str::snake($relationName).'.'.$relationColumn;
  316. }
  317. $column = $this->addColumn($name, $label);
  318. return $column;
  319. }
  320. /**
  321. * Add number column.
  322. *
  323. * @param null|string $label
  324. * @return Column
  325. */
  326. public function number(?string $label = null)
  327. {
  328. return $this->column('#', $label ?: '#')->bold();
  329. }
  330. /**
  331. * Batch add column to grid.
  332. *
  333. * @example
  334. * 1.$grid->columns(['name' => 'Name', 'email' => 'Email' ...]);
  335. * 2.$grid->columns('name', 'email' ...)
  336. *
  337. * @param array $columns
  338. *
  339. * @return null
  340. */
  341. public function columns($columns = [])
  342. {
  343. if (func_num_args() == 0) {
  344. return $this->columns;
  345. }
  346. if (func_num_args() == 1 && is_array($columns)) {
  347. foreach ($columns as $column => $label) {
  348. $this->column($column, $label);
  349. }
  350. return;
  351. }
  352. foreach (func_get_args() as $column) {
  353. $this->column($column);
  354. }
  355. }
  356. /**
  357. * @return Collection
  358. */
  359. public function getColumns()
  360. {
  361. return $this->columns;
  362. }
  363. /**
  364. * Add column to grid.
  365. *
  366. * @param string $field
  367. * @param string $label
  368. *
  369. * @return Column
  370. */
  371. protected function addColumn($field = '', $label = '')
  372. {
  373. $column = new Column($field, $label);
  374. $column->setGrid($this);
  375. $this->columns->put($field, $column);
  376. return $column;
  377. }
  378. /**
  379. * Prepend column to grid.
  380. *
  381. * @param string $column
  382. * @param string $label
  383. *
  384. * @return Column
  385. */
  386. protected function prependColumn($column = '', $label = '')
  387. {
  388. $column = new Column($column, $label);
  389. $column->setGrid($this);
  390. $this->columns->prepend($column);
  391. return $column;
  392. }
  393. /**
  394. * Get Grid model.
  395. *
  396. * @return Model
  397. */
  398. public function model()
  399. {
  400. return $this->model;
  401. }
  402. /**
  403. * @return array
  404. */
  405. public function getColumnNames()
  406. {
  407. return $this->columnNames;
  408. }
  409. /**
  410. * Paginate the grid.
  411. *
  412. * @param int $perPage
  413. *
  414. * @return void
  415. */
  416. public function paginate(int $perPage = 20)
  417. {
  418. $this->perPage = $perPage;
  419. $this->model()->setPerPage($perPage);
  420. }
  421. /**
  422. * @return int
  423. */
  424. public function getPerPage()
  425. {
  426. return $this->perPage;
  427. }
  428. /**
  429. * Get the grid paginator.
  430. *
  431. * @return mixed
  432. */
  433. public function paginator()
  434. {
  435. if (!$this->options['show_pagination']) {
  436. return;
  437. }
  438. return new Tools\Paginator($this);
  439. }
  440. /**
  441. * If this grid use pagination.
  442. *
  443. * @return bool
  444. */
  445. public function allowPagination()
  446. {
  447. return $this->options['show_pagination'];
  448. }
  449. /**
  450. * Set per-page options.
  451. *
  452. * @param array $perPages
  453. */
  454. public function perPages(array $perPages)
  455. {
  456. $this->perPages = $perPages;
  457. return $this;
  458. }
  459. /**
  460. * Get per-page options.
  461. *
  462. * @return array
  463. */
  464. public function getPerPages()
  465. {
  466. return $this->perPages;
  467. }
  468. /**
  469. * @param array $options
  470. * @return $this
  471. */
  472. public function setRowSelectorOptions(array $options = [])
  473. {
  474. if (isset($options['style'])) {
  475. $this->options['row_selector_style'] = $options['style'];
  476. }
  477. if (isset($options['circle'])) {
  478. $this->options['row_selector_circle'] = $options['circle'];
  479. }
  480. if (isset($options['clicktr'])) {
  481. $this->options['row_selector_clicktr'] = $options['clicktr'];
  482. }
  483. if (isset($options['label_name'])) {
  484. $this->options['row_selector_label_name'] = $options['label_name'];
  485. }
  486. if (isset($options['bg'])) {
  487. $this->options['row_selector_bg'] = $options['bg'];
  488. }
  489. return $this;
  490. }
  491. /**
  492. * Prepend checkbox column for grid.
  493. *
  494. * @return void
  495. */
  496. protected function prependRowSelectorColumn()
  497. {
  498. if (!$this->options['show_row_selector']) {
  499. return;
  500. }
  501. $circle = $this->options['row_selector_circle'] ? 'checkbox-circle' : '';
  502. $column = new Column(
  503. Column::SELECT_COLUMN_NAME,
  504. <<<HTML
  505. <div class="checkbox checkbox-{$this->options['row_selector_style']} $circle checkbox-grid">
  506. <input type="checkbox" class="select-all {$this->getSelectAllName()}"><label></label>
  507. </div>
  508. HTML
  509. );
  510. $column->setGrid($this);
  511. $column->displayUsing(Displayers\RowSelector::class);
  512. $this->columns->prepend($column, Column::SELECT_COLUMN_NAME);
  513. }
  514. /**
  515. * Apply column filter to grid query.
  516. */
  517. protected function applyColumnFilter()
  518. {
  519. $this->columns->each->bindFilterQuery($this->model());
  520. }
  521. /**
  522. * Build the grid.
  523. *
  524. * @return void
  525. */
  526. public function build()
  527. {
  528. if ($this->built) {
  529. return;
  530. }
  531. $this->applyQuickSearch();
  532. $this->applyColumnFilter();
  533. $collection = $this->processFilter(false);
  534. $data = $collection->toArray();
  535. $this->prependRowSelectorColumn();
  536. $this->appendActionsColumn();
  537. Column::setOriginalGridModels($collection);
  538. $this->columns->map(function (Column $column) use (&$data) {
  539. $column->fill($data);
  540. $this->columnNames[] = $column->getName();
  541. });
  542. $this->buildRows($data);
  543. $this->built = true;
  544. if ($data && $this->responsive) {
  545. $this->responsive->build();
  546. }
  547. $this->sortHeaders();
  548. }
  549. /**
  550. * @return Tools
  551. */
  552. public function getTools()
  553. {
  554. return $this->tools;
  555. }
  556. /**
  557. * Get filter of Grid.
  558. *
  559. * @return Filter
  560. */
  561. public function getFilter()
  562. {
  563. return $this->filter;
  564. }
  565. /**
  566. * Process the grid filter.
  567. *
  568. * @param bool $toArray
  569. *
  570. * @return array|Collection|mixed
  571. */
  572. public function processFilter($toArray = true)
  573. {
  574. if ($this->builder) {
  575. call_user_func($this->builder, $this);
  576. }
  577. return $this->filter->execute($toArray);
  578. }
  579. /**
  580. * Set the grid filter.
  581. *
  582. * @param Closure $callback
  583. * @return $this
  584. */
  585. public function filter(Closure $callback)
  586. {
  587. call_user_func($callback, $this->filter);
  588. return $this;
  589. }
  590. /**
  591. * Render the grid filter.
  592. *
  593. * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|string
  594. */
  595. public function renderFilter()
  596. {
  597. if (!$this->options['show_filter']) {
  598. return '';
  599. }
  600. return $this->filter->render();
  601. }
  602. /**
  603. * Expand filter.
  604. *
  605. * @return $this
  606. */
  607. public function expandFilter()
  608. {
  609. $this->filter->expand();
  610. return $this;
  611. }
  612. /**
  613. * Build the grid rows.
  614. *
  615. * @param array $data
  616. *
  617. * @return void
  618. */
  619. protected function buildRows(array $data)
  620. {
  621. $this->rows = collect($data)->map(function ($model) {
  622. return new Row($this, $model);
  623. });
  624. if ($this->rowsCallback) {
  625. foreach ($this->rowsCallback as $value) {
  626. $this->rows->map($value);
  627. }
  628. }
  629. }
  630. /**
  631. * Set grid row callback function.
  632. *
  633. * @param Closure $callable
  634. *
  635. * @return Collection|null
  636. */
  637. public function rows(Closure $callable = null)
  638. {
  639. if (is_null($callable)) {
  640. return $this->rows;
  641. }
  642. $this->rowsCallback[] = $callable;
  643. }
  644. /**
  645. * Setup grid tools.
  646. *
  647. * @param Closure $callback
  648. *
  649. * @return $this
  650. */
  651. public function tools(Closure $callback)
  652. {
  653. call_user_func($callback, $this->tools);
  654. return $this;
  655. }
  656. /**
  657. * Render custom tools.
  658. *
  659. * @return string
  660. */
  661. public function renderTools()
  662. {
  663. return $this->tools->render();
  664. }
  665. /**
  666. * Set exporter driver for Grid to export.
  667. *
  668. * @param $exporter
  669. *
  670. * @return $this
  671. */
  672. public function exporter($exporter)
  673. {
  674. $this->exporter = $exporter;
  675. return $this;
  676. }
  677. /**
  678. * Get the export url.
  679. *
  680. * @param int $scope
  681. * @param null $args
  682. *
  683. * @return string
  684. */
  685. public function getExportUrl($scope = 1, $args = null)
  686. {
  687. $input = array_merge(Input::all(), Exporter::formatExportQuery($scope, $args));
  688. if ($constraints = $this->model()->getConstraints()) {
  689. $input = array_merge($input, $constraints);
  690. }
  691. return $this->getResource().'?'.http_build_query($input);
  692. }
  693. /**
  694. * Get create url.
  695. *
  696. * @return string
  697. */
  698. public function getCreateUrl()
  699. {
  700. $queryString = '';
  701. if ($constraints = $this->model()->getConstraints()) {
  702. $queryString = http_build_query($constraints);
  703. }
  704. return sprintf('%s/create%s',
  705. $this->getResource(),
  706. $queryString ? ('?'.$queryString) : ''
  707. );
  708. }
  709. /**
  710. * @param string $width
  711. * @param string $height
  712. * @return $this
  713. */
  714. public function setDialogFormDimensions(string $width, string $height)
  715. {
  716. $this->options['dialog_form_area'] = [$width, $height];
  717. return $this;
  718. }
  719. /**
  720. * If grid show export btn.
  721. *
  722. * @return bool
  723. */
  724. public function allowExportBtn()
  725. {
  726. return $this->options['show_exporter'];
  727. }
  728. /**
  729. * @param int|null $limit
  730. * @return Grid
  731. */
  732. public function setExportLimit(?int $limit)
  733. {
  734. return $this->option('export_limit', $limit);
  735. }
  736. /**
  737. * Render export button.
  738. *
  739. * @return string
  740. */
  741. public function renderExportButton()
  742. {
  743. if (!$this->options['show_exporter']) {
  744. return '';
  745. }
  746. return (new Tools\ExportButton($this))->render();
  747. }
  748. /**
  749. * If allow creation.
  750. *
  751. * @return bool
  752. */
  753. public function allowCreateBtn()
  754. {
  755. return $this->options['show_create_btn'];
  756. }
  757. /**
  758. * @return bool
  759. */
  760. public function allowQuickCreateBtn()
  761. {
  762. return $this->options['show_quick_create_btn'];
  763. }
  764. /**
  765. * Render create button for grid.
  766. *
  767. * @return string
  768. */
  769. public function renderCreateButton()
  770. {
  771. if (!$this->options['show_create_btn'] && !$this->options['show_quick_create_btn']) {
  772. return '';
  773. }
  774. return (new Tools\CreateButton($this))->render();
  775. }
  776. /**
  777. * @return $this
  778. */
  779. public function withBorder()
  780. {
  781. $this->options['show_bordered'] = true;
  782. return $this;
  783. }
  784. /**
  785. * Set grid header.
  786. *
  787. * @param Closure|string|Renderable $content
  788. *
  789. * @return $this|Closure
  790. */
  791. public function header($content = null)
  792. {
  793. if (!$content) {
  794. return $this->header;
  795. }
  796. $this->header = $content;
  797. return $this;
  798. }
  799. /**
  800. * Render grid header.
  801. *
  802. * @return string
  803. */
  804. public function renderHeader()
  805. {
  806. if (!$this->header) {
  807. return '';
  808. }
  809. $content = Helper::render($this->header, [$this->processFilter(false)]);
  810. if (empty($content)) {
  811. return '';
  812. }
  813. if ($content instanceof Renderable) {
  814. $content = $content->render();
  815. }
  816. if ($content instanceof Htmlable) {
  817. $content = $content->toHtml();
  818. }
  819. return <<<HTML
  820. <div class="box-header clearfix" style="border-top:1px solid #ebeff2">{$content}</div>
  821. HTML;
  822. }
  823. /**
  824. * Set grid footer.
  825. *
  826. * @param Closure|string|Renderable $content
  827. *
  828. * @return $this|Closure
  829. */
  830. public function footer($content = null)
  831. {
  832. if (!$content) {
  833. return $this->footer;
  834. }
  835. $this->footer = $content;
  836. return $this;
  837. }
  838. /**
  839. * Render grid footer.
  840. *
  841. * @return string
  842. */
  843. public function renderFooter()
  844. {
  845. if (!$this->footer) {
  846. return '';
  847. }
  848. $content = Helper::render($this->footer, [$this->processFilter(false)]);
  849. if (empty($content)) {
  850. return '';
  851. }
  852. if ($content instanceof Renderable) {
  853. $content = $content->render();
  854. }
  855. if ($content instanceof Htmlable) {
  856. $content = $content->toHtml();
  857. }
  858. return <<<HTML
  859. <div class="box-footer clearfix">{$content}</div>
  860. HTML;
  861. }
  862. /**
  863. * Set resource path.
  864. *
  865. * @param string $path
  866. * @return $this
  867. */
  868. public function resource(string $path)
  869. {
  870. if (!empty($path)) {
  871. $this->resourcePath = admin_url($path);
  872. }
  873. return $this;
  874. }
  875. /**
  876. * Get resource path.
  877. *
  878. * @return string
  879. */
  880. public function getResource()
  881. {
  882. return $this->resourcePath ?: (
  883. $this->resourcePath = url(app('request')->getPathInfo())
  884. );
  885. }
  886. /**
  887. * @param Closure $closure
  888. * @return $this;
  889. */
  890. public function wrap(\Closure $closure)
  891. {
  892. $this->wrapper = $closure;
  893. return $this;
  894. }
  895. /**
  896. * @return bool
  897. */
  898. public function hasWrapper()
  899. {
  900. return $this->wrapper ? true : false;
  901. }
  902. /**
  903. * Add variables to grid view.
  904. *
  905. * @param array $variables
  906. *
  907. * @return $this
  908. */
  909. public function with($variables = [])
  910. {
  911. $this->variables = $variables;
  912. return $this;
  913. }
  914. /**
  915. * Get all variables will used in grid view.
  916. *
  917. * @return array
  918. */
  919. protected function variables()
  920. {
  921. $this->variables['grid'] = $this;
  922. $this->variables['tableId'] = $this->tableId;
  923. return $this->variables;
  924. }
  925. /**
  926. * Set a view to render.
  927. *
  928. * @param string $view
  929. * @param array $variables
  930. */
  931. public function setView($view, $variables = [])
  932. {
  933. if (!empty($variables)) {
  934. $this->with($variables);
  935. }
  936. $this->view = $view;
  937. }
  938. /**
  939. * Set grid title.
  940. *
  941. * @param string $title
  942. *
  943. * @return $this
  944. */
  945. public function setTitle($title)
  946. {
  947. $this->variables['title'] = $title;
  948. return $this;
  949. }
  950. /**
  951. * Set grid description.
  952. *
  953. * @param string $description
  954. *
  955. * @return $this
  956. */
  957. public function setDescription($description)
  958. {
  959. $this->variables['description'] = $description;
  960. return $this;
  961. }
  962. /**
  963. * Set resource path for grid.
  964. *
  965. * @param string $path
  966. *
  967. * @return $this
  968. */
  969. public function setResource($path)
  970. {
  971. $this->resourcePath = $path;
  972. return $this;
  973. }
  974. /**
  975. * Get the string contents of the grid view.
  976. *
  977. * @return string
  978. */
  979. public function render()
  980. {
  981. $this->handleExportRequest(true);
  982. try {
  983. $this->callComposing();
  984. $this->build();
  985. } catch (\Throwable $e) {
  986. return Admin::makeExceptionHandler()->renderException($e);
  987. }
  988. return $this->doWrap();
  989. }
  990. /**
  991. * @return string
  992. */
  993. protected function doWrap()
  994. {
  995. $view = view($this->view, $this->variables());
  996. if (!$wrapper = $this->wrapper) {
  997. return "<div class='box box-default'>{$view->render()}</div>";
  998. }
  999. return $wrapper($view);
  1000. }
  1001. /**
  1002. * Add column to grid.
  1003. *
  1004. * @param string $name
  1005. * @return Column|Collection
  1006. */
  1007. public function __get($name)
  1008. {
  1009. return $this->addColumn($name);
  1010. }
  1011. /**
  1012. * Dynamically add columns to the grid view.
  1013. *
  1014. * @param $method
  1015. * @param $arguments
  1016. *
  1017. * @return Column
  1018. */
  1019. public function __call($method, $arguments)
  1020. {
  1021. if (static::hasMacro($method)) {
  1022. return $this->macroCall($method, $arguments);
  1023. }
  1024. return $this->addColumn($method, $arguments[0] ?? null);
  1025. }
  1026. }