AbstractFilter.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. <?php
  2. namespace Dcat\Admin\Grid\Filter;
  3. use Dcat\Admin\Grid\Filter;
  4. use Dcat\Admin\Grid\Filter\Presenter\Checkbox;
  5. use Dcat\Admin\Grid\Filter\Presenter\DateTime;
  6. use Dcat\Admin\Grid\Filter\Presenter\MultipleSelect;
  7. use Dcat\Admin\Grid\Filter\Presenter\Presenter;
  8. use Dcat\Admin\Grid\Filter\Presenter\Radio;
  9. use Dcat\Admin\Grid\Filter\Presenter\Select;
  10. use Dcat\Admin\Grid\Filter\Presenter\Text;
  11. use Illuminate\Support\Arr;
  12. use Illuminate\Support\Collection;
  13. /**
  14. * Class AbstractFilter.
  15. *
  16. * @method Text url()
  17. * @method Text email()
  18. * @method Text integer()
  19. * @method Text decimal($options = [])
  20. * @method Text currency($options = [])
  21. * @method Text percentage($options = [])
  22. * @method Text ip()
  23. * @method Text mac()
  24. * @method Text mobile($mask = '19999999999')
  25. * @method Text inputmask($options = [], $icon = '')
  26. * @method Text placeholder($placeholder = '')
  27. */
  28. abstract class AbstractFilter
  29. {
  30. /**
  31. * Element id.
  32. *
  33. * @var array|string
  34. */
  35. protected $id;
  36. /**
  37. * Label of presenter.
  38. *
  39. * @var string
  40. */
  41. protected $label;
  42. /**
  43. * @var array|string
  44. */
  45. protected $value;
  46. /**
  47. * @var array|string
  48. */
  49. protected $defaultValue;
  50. /**
  51. * @var string
  52. */
  53. protected $column;
  54. /**
  55. * Presenter object.
  56. *
  57. * @var Presenter
  58. */
  59. protected $presenter;
  60. /**
  61. * Query for filter.
  62. *
  63. * @var string
  64. */
  65. protected $query = 'where';
  66. /**
  67. * @var Filter
  68. */
  69. protected $parent;
  70. /**
  71. * @var int
  72. */
  73. protected $width = 10;
  74. /**
  75. * @var string
  76. */
  77. protected $style;
  78. /**
  79. * @var string
  80. */
  81. protected $view = 'admin::filter.where';
  82. /**
  83. * @var Collection
  84. */
  85. public $group;
  86. /**
  87. * AbstractFilter constructor.
  88. *
  89. * @param $column
  90. * @param string $label
  91. */
  92. public function __construct($column, $label = '')
  93. {
  94. $this->column = $column;
  95. $this->label = $this->formatLabel($label);
  96. }
  97. /**
  98. * Setup default presenter.
  99. *
  100. * @return void
  101. */
  102. protected function setupDefaultPresenter()
  103. {
  104. $this->setPresenter(new Text($this->label));
  105. }
  106. /**
  107. * Format label.
  108. *
  109. * @param string $label
  110. *
  111. * @return string
  112. */
  113. protected function formatLabel($label)
  114. {
  115. $label = $label ?: admin_trans_field($this->column);
  116. return str_replace(['.', '_'], ' ', $label);
  117. }
  118. /**
  119. * Set the column width.
  120. *
  121. * @param int|string $width
  122. *
  123. * @return $this
  124. */
  125. public function width($width)
  126. {
  127. if (is_numeric($width)) {
  128. $this->width = $width;
  129. } else {
  130. $this->style = "width:$width;padding-left:10px;padding-right:10px";
  131. $this->width = ' ';
  132. }
  133. return $this;
  134. }
  135. /**
  136. * Format name.
  137. *
  138. * @param string $column
  139. *
  140. * @return string
  141. */
  142. protected function formatName($column)
  143. {
  144. $columns = explode('.', $column);
  145. if (count($columns) == 1) {
  146. $name = $columns[0];
  147. } else {
  148. $name = array_shift($columns);
  149. foreach ($columns as $column) {
  150. $name .= "[$column]";
  151. }
  152. }
  153. $parenName = $this->parent->getName();
  154. return $parenName ? "{$parenName}_{$name}" : $name;
  155. }
  156. /**
  157. * Format id.
  158. *
  159. * @param $columns
  160. *
  161. * @return array|string
  162. */
  163. protected function formatId($columns)
  164. {
  165. return 'filter_column_'.$this->parent->grid()->getName().'_'.str_replace('.', '_', $columns);
  166. }
  167. /**
  168. * @param Filter $filter
  169. */
  170. public function setParent(Filter $filter)
  171. {
  172. $this->parent = $filter;
  173. $this->id = $this->formatId($this->column);
  174. }
  175. /**
  176. * Get siblings of current filter.
  177. *
  178. * @param null $index
  179. *
  180. * @return AbstractFilter[]|mixed
  181. */
  182. public function siblings($index = null)
  183. {
  184. if (! is_null($index)) {
  185. return Arr::get($this->parent->filters(), $index);
  186. }
  187. return $this->parent->filters();
  188. }
  189. /**
  190. * Get previous filter.
  191. *
  192. * @param int $step
  193. *
  194. * @return AbstractFilter[]|mixed
  195. */
  196. public function previous($step = 1)
  197. {
  198. return $this->siblings(
  199. array_search($this, $this->parent->filters()) - $step
  200. );
  201. }
  202. /**
  203. * Get next filter.
  204. *
  205. * @param int $step
  206. *
  207. * @return AbstractFilter[]|mixed
  208. */
  209. public function next($step = 1)
  210. {
  211. return $this->siblings(
  212. array_search($this, $this->parent->filters()) + $step
  213. );
  214. }
  215. /**
  216. * Get query condition from filter.
  217. *
  218. * @param array $inputs
  219. *
  220. * @return array|mixed|null
  221. */
  222. public function condition($inputs)
  223. {
  224. $value = Arr::get($inputs, $this->column);
  225. if ($value === null) {
  226. return;
  227. }
  228. $this->value = $value;
  229. return $this->buildCondition($this->column, $this->value);
  230. }
  231. /**
  232. * Select filter.
  233. *
  234. * @param array $options
  235. *
  236. * @return Select
  237. */
  238. public function select($options = [])
  239. {
  240. return $this->setPresenter(new Select($options));
  241. }
  242. /**
  243. * @param array $options
  244. *
  245. * @return MultipleSelect
  246. */
  247. public function multipleSelect($options = [])
  248. {
  249. return $this->setPresenter(new MultipleSelect($options));
  250. }
  251. /**
  252. * @param mixed $source
  253. *
  254. * @return Filter\Presenter\SelectResource
  255. */
  256. public function selectResource($source = null)
  257. {
  258. return $this->setPresenter(new Filter\Presenter\SelectResource($source));
  259. }
  260. /**
  261. * @param array $options
  262. *
  263. * @return Radio
  264. */
  265. public function radio($options = [])
  266. {
  267. return $this->setPresenter(new Radio($options));
  268. }
  269. /**
  270. * @param array $options
  271. *
  272. * @return Checkbox
  273. */
  274. public function checkbox($options = [])
  275. {
  276. return $this->setPresenter(new Checkbox($options));
  277. }
  278. /**
  279. * Datetime filter.
  280. *
  281. * @param array $options
  282. *
  283. * @return DateTime
  284. */
  285. public function datetime($options = [])
  286. {
  287. return $this->setPresenter(new DateTime($options));
  288. }
  289. /**
  290. * Date filter.
  291. *
  292. * @return DateTime
  293. */
  294. public function date()
  295. {
  296. return $this->datetime(['format' => 'YYYY-MM-DD']);
  297. }
  298. /**
  299. * Time filter.
  300. *
  301. * @return DateTime
  302. */
  303. public function time()
  304. {
  305. return $this->datetime(['format' => 'HH:mm:ss']);
  306. }
  307. /**
  308. * Day filter.
  309. *
  310. * @return DateTime
  311. */
  312. public function day()
  313. {
  314. return $this->datetime(['format' => 'DD']);
  315. }
  316. /**
  317. * Month filter.
  318. *
  319. * @return DateTime
  320. */
  321. public function month()
  322. {
  323. return $this->datetime(['format' => 'YYYY-MM']);
  324. }
  325. /**
  326. * Year filter.
  327. *
  328. * @return DateTime
  329. */
  330. public function year()
  331. {
  332. return $this->datetime(['format' => 'YYYY']);
  333. }
  334. /**
  335. * Set presenter object of filter.
  336. *
  337. * @param Presenter $presenter
  338. *
  339. * @return mixed
  340. */
  341. public function setPresenter(Presenter $presenter)
  342. {
  343. $presenter->setParent($this);
  344. $presenter::collectAssets();
  345. return $this->presenter = $presenter;
  346. }
  347. /**
  348. * Get presenter object of filter.
  349. *
  350. * @return Presenter
  351. */
  352. protected function presenter()
  353. {
  354. if (! $this->presenter) {
  355. $this->setupDefaultPresenter();
  356. }
  357. return $this->presenter;
  358. }
  359. /**
  360. * Set default value for filter.
  361. *
  362. * @param null $default
  363. *
  364. * @return $this
  365. */
  366. public function default($default = null)
  367. {
  368. if ($default) {
  369. $this->defaultValue = $default;
  370. }
  371. return $this;
  372. }
  373. public function getDefault()
  374. {
  375. return $this->defaultValue;
  376. }
  377. /**
  378. * Get element id.
  379. *
  380. * @return array|string
  381. */
  382. public function getId()
  383. {
  384. return $this->id;
  385. }
  386. /**
  387. * Set element id.
  388. *
  389. * @param string $id
  390. *
  391. * @return $this
  392. */
  393. public function setId($id)
  394. {
  395. $this->id = $this->formatId($id);
  396. return $this;
  397. }
  398. /**
  399. * Get column name of current filter.
  400. *
  401. * @return string
  402. */
  403. public function column()
  404. {
  405. $parenName = $this->parent->getName();
  406. return $parenName ? "{$parenName}_{$this->column}" : $this->column;
  407. }
  408. /**
  409. * Get value of current filter.
  410. *
  411. * @return array|string
  412. */
  413. public function getValue()
  414. {
  415. return $this->value;
  416. }
  417. /**
  418. * @param mixed $value
  419. *
  420. * @return $this
  421. */
  422. public function setValue($value)
  423. {
  424. $this->value = $value;
  425. return $this;
  426. }
  427. /**
  428. * Build conditions of filter.
  429. *
  430. * @return mixed
  431. */
  432. protected function buildCondition(...$params)
  433. {
  434. $column = explode('.', $this->column);
  435. if (count($column) == 1) {
  436. return [$this->query => &$params];
  437. }
  438. return $this->buildRelationQuery(...$params);
  439. }
  440. /**
  441. * @param mixed ...$params
  442. *
  443. * @return array
  444. */
  445. protected function buildRelationQuery(...$params)
  446. {
  447. $relation = substr($this->column, 0, strrpos($this->column, '.'));
  448. $params[0] = Arr::last(explode('.', $this->column));
  449. return ['whereHas' => [$relation, function ($relation) use ($params) {
  450. call_user_func_array([$relation, $this->query], $params);
  451. }]];
  452. }
  453. /**
  454. * Variables for filter view.
  455. *
  456. * @return array
  457. */
  458. protected function variables()
  459. {
  460. $variables = $this->presenter()->variables();
  461. $value = $this->value ?: Arr::get($this->parent->inputs(), $this->column);
  462. return array_merge([
  463. 'id' => $this->id,
  464. 'name' => $this->formatName($this->column),
  465. 'label' => $this->label,
  466. 'value' => $value ?: $this->defaultValue,
  467. 'presenter' => $this->presenter(),
  468. 'width' => $this->width,
  469. 'style' => $this->style,
  470. ], $variables);
  471. }
  472. /**
  473. * Render this filter.
  474. *
  475. * @return \Illuminate\View\View|string
  476. */
  477. public function render()
  478. {
  479. return view($this->view, $this->variables());
  480. }
  481. /**
  482. * Render this filter.
  483. *
  484. * @return \Illuminate\View\View|string
  485. */
  486. public function __toString()
  487. {
  488. return $this->render();
  489. }
  490. /**
  491. * @param $method
  492. * @param $params
  493. *
  494. * @throws \Exception
  495. *
  496. * @return mixed
  497. */
  498. public function __call($method, $params)
  499. {
  500. if (method_exists($this->presenter(), $method)) {
  501. return $this->presenter()->{$method}(...$params);
  502. }
  503. throw new \BadMethodCallException(sprintf(
  504. 'Call to undefined method %s::%s()', static::class, $method
  505. ));
  506. }
  507. }