Show.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. <?php
  2. namespace Dcat\Admin;
  3. use Dcat\Admin\Contracts\Repository;
  4. use Dcat\Admin\Show\Divider;
  5. use Dcat\Admin\Show\Field;
  6. use Dcat\Admin\Show\Newline;
  7. use Dcat\Admin\Show\Panel;
  8. use Dcat\Admin\Show\Relation;
  9. use Dcat\Admin\Traits\BuilderEvents;
  10. use Illuminate\Contracts\Support\Renderable;
  11. use Illuminate\Database\Eloquent\Model;
  12. use Illuminate\Support\Arr;
  13. use Illuminate\Support\Collection;
  14. use Illuminate\Support\Facades\URL;
  15. use Illuminate\Support\Fluent;
  16. class Show implements Renderable
  17. {
  18. use BuilderEvents;
  19. /**
  20. * @var string
  21. */
  22. protected $view = 'admin::show';
  23. /**
  24. * @var Repository
  25. */
  26. protected $repository;
  27. /**
  28. * @var mixed
  29. */
  30. protected $_id;
  31. /**
  32. * @var Fluent
  33. */
  34. protected $model;
  35. /**
  36. * Show panel builder.
  37. *
  38. * @var callable
  39. */
  40. protected $builder;
  41. /**
  42. * Resource path for this show page.
  43. *
  44. * @var string
  45. */
  46. protected $resource;
  47. /**
  48. * Fields to be show.
  49. *
  50. * @var Collection
  51. */
  52. protected $fields;
  53. /**
  54. * Relations to be show.
  55. *
  56. * @var Collection
  57. */
  58. protected $relations;
  59. /**
  60. * @var Panel
  61. */
  62. protected $panel;
  63. /**
  64. * Show constructor.
  65. *
  66. * @param Model $model
  67. * @param mixed $builder
  68. */
  69. public function __construct(Repository $repository, $builder = null)
  70. {
  71. $this->repository = Admin::createRepository($repository);
  72. $this->builder = $builder;
  73. $this->initPanel();
  74. $this->initContents();
  75. $this->callResolving();
  76. }
  77. /**
  78. * Create a show instance.
  79. *
  80. * @param mixed ...$params
  81. * @return $this
  82. */
  83. public static function make(...$params)
  84. {
  85. return new static(...$params);
  86. }
  87. /**
  88. * Get primary key name of model.
  89. *
  90. * @return string
  91. */
  92. public function getKeyName()
  93. {
  94. return $this->repository->getKeyName();
  95. }
  96. /**
  97. * @param mixed $id
  98. */
  99. public function setId($id)
  100. {
  101. $this->_id = $id;
  102. }
  103. /**
  104. * @return mixed
  105. */
  106. public function getId()
  107. {
  108. return $this->_id;
  109. }
  110. /**
  111. * @param $model
  112. */
  113. public function setModel(Fluent $model)
  114. {
  115. $this->model = $model;
  116. }
  117. /**
  118. * @return Fluent
  119. */
  120. public function getModel()
  121. {
  122. if (!$this->model) {
  123. $this->setModel(new Fluent($this->repository->detail($this)));
  124. }
  125. return $this->model;
  126. }
  127. /**
  128. * Set a view to render.
  129. *
  130. * @param string $view
  131. * @param array $variables
  132. * @return $this
  133. */
  134. public function setView($view, $variables = [])
  135. {
  136. if (!empty($variables)) {
  137. $this->with($variables);
  138. }
  139. $this->panel->setView($view);
  140. return $this;
  141. }
  142. /**
  143. * Add variables to show view.
  144. *
  145. * @param array $variables
  146. * @return $this
  147. */
  148. public function with($variables = [])
  149. {
  150. $this->panel->with($variables);
  151. return $this;
  152. }
  153. /**
  154. * @return $this
  155. */
  156. public function wrap(\Closure $wrapper)
  157. {
  158. $this->panel->wrap($wrapper);
  159. return $this;
  160. }
  161. /**
  162. * Initialize the contents to show.
  163. */
  164. protected function initContents()
  165. {
  166. $this->fields = new Collection();
  167. $this->relations = new Collection();
  168. }
  169. /**
  170. * Initialize panel.
  171. */
  172. protected function initPanel()
  173. {
  174. $this->panel = new Panel($this);
  175. }
  176. /**
  177. * Get panel instance.
  178. *
  179. * @return Panel
  180. */
  181. public function panel()
  182. {
  183. return $this->panel;
  184. }
  185. /**
  186. * Add a model field to show.
  187. *
  188. * @param string $name
  189. * @param string $label
  190. *
  191. * @return Field
  192. */
  193. public function field($name, $label = '')
  194. {
  195. return $this->addField($name, $label);
  196. }
  197. /**
  198. * Add multiple fields.
  199. *
  200. * @param array $fields
  201. *
  202. * @return $this
  203. */
  204. public function fields(array $fields = [])
  205. {
  206. if (!Arr::isAssoc($fields)) {
  207. $fields = array_combine($fields, $fields);
  208. }
  209. foreach ($fields as $field => $label) {
  210. $this->field($field, $label);
  211. }
  212. return $this;
  213. }
  214. /**
  215. * @return Collection
  216. */
  217. public function getFields()
  218. {
  219. return $this->fields;
  220. }
  221. /**
  222. * @return Collection
  223. */
  224. public function getRelations()
  225. {
  226. return $this->relations;
  227. }
  228. /**
  229. * Show all fields.
  230. *
  231. * @return Show
  232. */
  233. public function all()
  234. {
  235. $fields = array_keys($this->getModel()->toArray());
  236. return $this->fields($fields);
  237. }
  238. /**
  239. * Add a relation to show.
  240. *
  241. * @param string $name
  242. * @param string|\Closure $label
  243. * @param null|\Closure $builder
  244. *
  245. * @return Relation
  246. */
  247. public function relation($name, $label, $builder = null)
  248. {
  249. if (is_null($builder)) {
  250. $builder = $label;
  251. $label = '';
  252. }
  253. return $this->addRelation($name, $builder, $label);
  254. }
  255. /**
  256. * Add a model field to show.
  257. *
  258. * @param string $name
  259. * @param string $label
  260. *
  261. * @return Field
  262. */
  263. protected function addField($name, $label = '')
  264. {
  265. $field = new Field($name, $label);
  266. $field->setParent($this);
  267. $this->overwriteExistingField($name);
  268. $this->fields->push($field);
  269. return $field;
  270. }
  271. /**
  272. * Add a relation panel to show.
  273. *
  274. * @param string $name
  275. * @param \Closure $builder
  276. * @param string $label
  277. *
  278. * @return Relation
  279. */
  280. protected function addRelation($name, $builder, $label = '')
  281. {
  282. $relation = new Relation($name, $builder, $label);
  283. $relation->setParent($this);
  284. $this->overwriteExistingRelation($name);
  285. $this->relations->push($relation);
  286. return $relation;
  287. }
  288. /**
  289. * Overwrite existing field.
  290. *
  291. * @param string $name
  292. */
  293. protected function overwriteExistingField($name)
  294. {
  295. if ($this->fields->isEmpty()) {
  296. return;
  297. }
  298. $this->fields = $this->fields->filter(
  299. function (Field $field) use ($name) {
  300. return $field->getName() != $name;
  301. }
  302. );
  303. }
  304. /**
  305. * Overwrite existing relation.
  306. *
  307. * @param string $name
  308. */
  309. protected function overwriteExistingRelation($name)
  310. {
  311. if ($this->relations->isEmpty()) {
  312. return;
  313. }
  314. $this->relations = $this->relations->filter(
  315. function (Relation $relation) use ($name) {
  316. return $relation->getName() != $name;
  317. }
  318. );
  319. }
  320. /**
  321. * @return Repository
  322. */
  323. public function getRepository(): Repository
  324. {
  325. return $this->repository;
  326. }
  327. /**
  328. * Show a divider.
  329. */
  330. public function divider()
  331. {
  332. $this->fields->push(new Divider());
  333. }
  334. /**
  335. * Show a divider.
  336. */
  337. public function newline()
  338. {
  339. $this->fields->push(new Newline());
  340. }
  341. /**
  342. * Disable `list` tool.
  343. *
  344. * @return $this
  345. */
  346. public function disableListButton(bool $disable = true)
  347. {
  348. $this->panel->getTools()->disableList($disable);
  349. return $this;
  350. }
  351. /**
  352. * Disable `delete` tool.
  353. *
  354. * @return $this
  355. */
  356. public function disableDeleteButton(bool $disable = true)
  357. {
  358. $this->panel->getTools()->disableDelete($disable);
  359. return $this;
  360. }
  361. /**
  362. * Disable `edit` tool.
  363. *
  364. * @return $this
  365. */
  366. public function disableEditButton(bool $disable = true)
  367. {
  368. $this->panel->getTools()->disableEdit($disable);
  369. return $this;
  370. }
  371. /**
  372. * Show quick edit tool.
  373. *
  374. * @param null|string $width
  375. * @param null|string $height
  376. * @return $this
  377. */
  378. public function showQuickEdit(?string $width = null, ?string $height = null)
  379. {
  380. $this->panel->getTools()->showQuickEdit($width, $height);
  381. return $this;
  382. }
  383. /**
  384. * Disable quick edit tool.
  385. *
  386. * @return $this
  387. */
  388. public function disableQuickEdit()
  389. {
  390. $this->panel->getTools()->disableQuickEdit();
  391. return $this;
  392. }
  393. /**
  394. * Set resource path.
  395. *
  396. * @param string $resource
  397. *
  398. * @return $this
  399. */
  400. public function resource(string $resource)
  401. {
  402. if ($resource) {
  403. $this->resource = URL::isValidUrl($resource) ? $resource : admin_base_path($resource);
  404. }
  405. return $this;
  406. }
  407. /**
  408. * Get resource path.
  409. *
  410. * @return string
  411. */
  412. public function getResource()
  413. {
  414. if (empty($this->resource)) {
  415. $path = request()->path();
  416. $segments = explode('/', $path);
  417. array_pop($segments);
  418. $this->resource = implode('/', $segments);
  419. }
  420. return $this->resource;
  421. }
  422. /**
  423. * Add field and relation dynamically.
  424. *
  425. * @param string $method
  426. * @param array $arguments
  427. *
  428. * @return Field
  429. */
  430. public function __call($method, $arguments = [])
  431. {
  432. return $this->call($method, $arguments);
  433. }
  434. /**
  435. * @param $method
  436. * @param array $arguments
  437. * @return bool|Show|Field|Relation
  438. */
  439. protected function call($method, $arguments = [])
  440. {
  441. $label = isset($arguments[0]) ? $arguments[0] : '';
  442. if ($field = $this->handleRelationField($method, $arguments)) {
  443. return $field;
  444. }
  445. return $this->addField($method, $label);
  446. }
  447. /**
  448. * Handle relation field.
  449. *
  450. * @param string $method
  451. * @param array $arguments
  452. *
  453. * @return $this|bool|Relation|Field
  454. */
  455. protected function handleRelationField($method, $arguments)
  456. {
  457. if (count($arguments) == 1 && $arguments[0] instanceof \Closure) {
  458. return $this->addRelation($method, $arguments[0]);
  459. } elseif (count($arguments) == 2 && $arguments[1] instanceof \Closure) {
  460. return $this->addRelation($method, $arguments[1], $arguments[0]);
  461. }
  462. return false;
  463. }
  464. /**
  465. * Render the show panels.
  466. *
  467. * @return string
  468. */
  469. public function render()
  470. {
  471. $model = $this->getModel();
  472. if (is_callable($this->builder)) {
  473. call_user_func($this->builder, $this);
  474. }
  475. if ($this->fields->isEmpty()) {
  476. $this->all();
  477. }
  478. if (is_array($this->builder)) {
  479. $this->fields($this->builder);
  480. }
  481. $this->fields->each->setValue($model);
  482. $this->relations->each->setModel($model);
  483. $this->callComposing();
  484. $data = [
  485. 'panel' => $this->panel->fill($this->fields),
  486. 'relations' => $this->relations,
  487. ];
  488. return view($this->view, $data)->render();
  489. }
  490. /**
  491. * Add a model field to show.
  492. *
  493. * @param string $name
  494. * @return Field|Collection
  495. */
  496. public function __get($name)
  497. {
  498. return $this->call($name);
  499. }
  500. }