/src/Display/Display.php

https://github.com/LaravelRUS/SleepingOwlAdmin · PHP · 317 lines · 157 code · 49 blank · 111 comment · 10 complexity · 7edca2144c6c45156fa70eb2c92e32fd MD5 · raw file

  1. <?php
  2. namespace SleepingOwl\Admin\Display;
  3. use Exception;
  4. use Illuminate\Support\Arr;
  5. use Illuminate\Support\Str;
  6. use KodiComponents\Support\HtmlAttributes;
  7. use SleepingOwl\Admin\Contracts\Display\DisplayExtensionInterface;
  8. use SleepingOwl\Admin\Contracts\Display\DisplayInterface;
  9. use SleepingOwl\Admin\Contracts\Display\Extension\ActionInterface;
  10. use SleepingOwl\Admin\Contracts\Display\Extension\FilterInterface;
  11. use SleepingOwl\Admin\Contracts\ModelConfigurationInterface;
  12. use SleepingOwl\Admin\Contracts\Repositories\RepositoryInterface;
  13. use SleepingOwl\Admin\Display\Extension\Actions;
  14. use SleepingOwl\Admin\Display\Extension\ActionsForm;
  15. use SleepingOwl\Admin\Display\Extension\Apply;
  16. use SleepingOwl\Admin\Display\Extension\Filters;
  17. use SleepingOwl\Admin\Display\Extension\Links;
  18. use SleepingOwl\Admin\Display\Extension\Scopes;
  19. use SleepingOwl\Admin\Form\FormElements;
  20. use SleepingOwl\Admin\Traits\Assets;
  21. use SleepingOwl\Admin\Traits\Renderable;
  22. /**
  23. * Class Display.
  24. *
  25. * @method Actions getActions()
  26. * @method $this setActions(ActionInterface|array $action, ...$actions)
  27. *
  28. * @method ActionsForm getActionsForm()
  29. * @method $this setActionsForm(ActionInterface|array|FormElements $action, ...$actions)
  30. *
  31. * @method Filters getFilters()
  32. * @method $this setFilters(FilterInterface $filter, ...$filters)
  33. *
  34. * @method Apply getApply()
  35. * @method $this setApply(\Closure $apply, ...$applies)
  36. *
  37. * @method Scopes getScopes()
  38. * @method $this setScopes(array $scope, ...$scopes)
  39. */
  40. abstract class Display implements DisplayInterface
  41. {
  42. use HtmlAttributes, Assets, Renderable;
  43. /**
  44. * @var string
  45. */
  46. protected $modelClass;
  47. /**
  48. * @var array
  49. */
  50. protected $with = [];
  51. /**
  52. * @var string
  53. */
  54. protected $title;
  55. /**
  56. * @var string
  57. */
  58. protected $repositoryClass = RepositoryInterface::class;
  59. /**
  60. * @var RepositoryInterface
  61. */
  62. protected $repository;
  63. /**
  64. * @var DisplayExtensionInterface[]|ExtensionCollection
  65. */
  66. protected $extensions;
  67. /**
  68. * @var bool
  69. */
  70. protected $initialized = false;
  71. /**
  72. * Display constructor.
  73. */
  74. public function __construct()
  75. {
  76. $this->extensions = new ExtensionCollection();
  77. $this->extend('actions_form', new ActionsForm());
  78. $this->extend('actions', new Actions());
  79. $this->extend('filters', new Filters());
  80. $this->extend('apply', new Apply());
  81. $this->extend('scopes', new Scopes());
  82. $this->extend('links', new Links());
  83. $this->initializePackage();
  84. }
  85. /**
  86. * @return bool
  87. */
  88. public function isInitialized()
  89. {
  90. return $this->initialized;
  91. }
  92. /**
  93. * @param string $name
  94. * @param DisplayExtensionInterface $extension
  95. *
  96. * @return DisplayExtensionInterface
  97. */
  98. public function extend($name, DisplayExtensionInterface $extension)
  99. {
  100. $this->extensions->put($name, $extension);
  101. $extension->setDisplay($this);
  102. return $extension;
  103. }
  104. /**
  105. * @return ExtensionCollection|DisplayExtensionInterface[]
  106. */
  107. public function getExtensions()
  108. {
  109. return $this->extensions;
  110. }
  111. /**
  112. * @return RepositoryInterface
  113. */
  114. public function getRepository()
  115. {
  116. return $this->repository;
  117. }
  118. /**
  119. * @param $repositoryClass
  120. *
  121. * @return $this
  122. */
  123. public function setRepositoryClass($repositoryClass)
  124. {
  125. $this->repositoryClass = $repositoryClass;
  126. return $this;
  127. }
  128. /**
  129. * @param array|string[] ...$relations
  130. *
  131. * @return $this
  132. */
  133. public function with($relations)
  134. {
  135. $this->with = Arr::flatten(func_get_args());
  136. return $this;
  137. }
  138. /**
  139. * @throws \Exception
  140. */
  141. public function initialize()
  142. {
  143. if ($this->isInitialized()) {
  144. return;
  145. }
  146. $this->repository = $this->makeRepository();
  147. $this->repository->with($this->with);
  148. $this->extensions->initialize();
  149. $this->includePackage();
  150. $this->initialized = true;
  151. }
  152. /**
  153. * @param string $modelClass
  154. *
  155. * @return $this
  156. */
  157. public function setModelClass($modelClass)
  158. {
  159. if (is_null($this->modelClass)) {
  160. $this->modelClass = $modelClass;
  161. }
  162. return $this;
  163. }
  164. /**
  165. * @return string
  166. */
  167. public function getTitle()
  168. {
  169. $titles = [
  170. $this->title,
  171. ];
  172. $this->getExtensions()->each(function (DisplayExtensionInterface $extension) use (&$titles) {
  173. if (method_exists($extension, $method = 'getTitle')) {
  174. $titles[] = call_user_func([$extension, $method]);
  175. }
  176. });
  177. return implode(' | ', array_filter($titles));
  178. }
  179. /**
  180. * @param string $title
  181. *
  182. * @return $this
  183. */
  184. public function setTitle($title)
  185. {
  186. $this->title = $title;
  187. return $this;
  188. }
  189. /**
  190. * Get the instance as an array.
  191. *
  192. * @return array
  193. */
  194. public function toArray()
  195. {
  196. return [
  197. 'title' => $this->getTitle(),
  198. 'extensions' => $this->getExtensions()->toArray(),
  199. 'attributes' => $this->htmlAttributesToString(),
  200. ];
  201. }
  202. /**
  203. * Get the evaluated contents of the object.
  204. *
  205. * @return string
  206. */
  207. public function render()
  208. {
  209. $view = app('sleeping_owl.template')->view($this->getView(), $this->toArray());
  210. $blocks = $this->getExtensions()->placableBlocks();
  211. // Flush all view yields before render new Section
  212. $view->getFactory()->flushSections();
  213. foreach ($blocks as $block => $data) {
  214. foreach ($data as $html) {
  215. if (! empty($html)) {
  216. $view->getFactory()->startSection($block);
  217. echo $html;
  218. $view->getFactory()->yieldSection();
  219. } else {
  220. /*
  221. * Need test for action (BUG)
  222. */
  223. //$view->getFactory()->flushSections();
  224. }
  225. }
  226. }
  227. return $view;
  228. }
  229. /**
  230. * @param string $name
  231. * @param array $arguments
  232. *
  233. * @return DisplayExtensionInterface
  234. */
  235. public function __call($name, $arguments)
  236. {
  237. $method = Str::snake(substr($name, 3));
  238. if (Str::startsWith($name, 'get') && $this->extensions->has($method)) {
  239. return $this->extensions->get($method);
  240. } elseif (Str::startsWith($name, 'set') && $this->extensions->has($method)) {
  241. $extension = $this->extensions->get($method);
  242. if (method_exists($extension, 'set')) {
  243. return call_user_func_array([$extension, 'set'], $arguments);
  244. }
  245. }
  246. throw new \BadMethodCallException("Call to undefined method [{$name}]");
  247. }
  248. /**
  249. * @return ModelConfigurationInterface
  250. */
  251. public function getModelConfiguration()
  252. {
  253. return app('sleeping_owl')->getModel($this->modelClass);
  254. }
  255. /**
  256. * @return \Illuminate\Foundation\Application|mixed
  257. * @throws \Exception
  258. */
  259. protected function makeRepository()
  260. {
  261. $repository = app($this->repositoryClass);
  262. if (! ($repository instanceof RepositoryInterface)) {
  263. throw new Exception('Repository class must be instanced of [RepositoryInterface]');
  264. }
  265. $repository->setClass($this->modelClass);
  266. return $repository;
  267. }
  268. }