Grid.php 24 KB

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