SectionManager.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. <?php
  2. namespace Dcat\Admin\Layout;
  3. use Dcat\Admin\Support\Helper;
  4. use Illuminate\Contracts\Support\Htmlable;
  5. use Illuminate\Contracts\Support\Renderable;
  6. use Illuminate\Support\Fluent;
  7. class SectionManager
  8. {
  9. /**
  10. * All of the finished, captured sections.
  11. *
  12. * @var array
  13. */
  14. protected $sections = [];
  15. /**
  16. * @var array
  17. */
  18. protected $defaultSections = [];
  19. /**
  20. * Inject content into a section.
  21. *
  22. * @param string $section
  23. * @param string|Renderable|Htmlable|callable $content
  24. * @param bool $append
  25. * @param int $priority
  26. *
  27. * @return void
  28. */
  29. public function inject($section, $content, bool $append = true, int $priority = 10)
  30. {
  31. $this->put($section, $content, $append, $priority);
  32. }
  33. /**
  34. * @param string $section
  35. * @param string|Renderable|Htmlable|callable $content
  36. *
  37. * @return void
  38. */
  39. public function injectDefault(string $section, $content)
  40. {
  41. if ($this->hasSection($section)) {
  42. return;
  43. }
  44. $this->defaultSections[$section] = &$content;
  45. }
  46. /**
  47. * Set content to a given section.
  48. *
  49. * @param string $section
  50. * @param string|Renderable|Htmlable|callable $content
  51. * @param bool $append
  52. * @param int $priority
  53. *
  54. * @return void
  55. */
  56. protected function put(string $section, $content, bool $append = false, int $priority = 10)
  57. {
  58. if (! $section) {
  59. throw new \InvalidArgumentException('Section name is required.');
  60. }
  61. if (! isset($this->sections[$section])) {
  62. unset($this->defaultSections[$section]);
  63. $this->sections[$section] = [];
  64. }
  65. if (! isset($this->sections[$section][$priority])) {
  66. $this->sections[$section][$priority] = [];
  67. }
  68. $this->sections[$section][$priority][] = [
  69. 'append' => $append,
  70. 'value' => &$content,
  71. ];
  72. }
  73. /**
  74. * Get the string contents of a section.
  75. *
  76. * @param string $section
  77. * @param mixed $default
  78. * @param array $options
  79. *
  80. * @return string
  81. */
  82. public function yieldContent(string $section, $default = '', array $options = [])
  83. {
  84. $defaultSection = $this->defaultSections[$section] ?? null;
  85. if (! $this->hasSection($section) && $defaultSection === null) {
  86. return Helper::render($default, [new Fluent()]);
  87. }
  88. $content = $this->getSections($section) ?: $defaultSection;
  89. return $this->resolveContent($section, $content, $options);
  90. }
  91. /**
  92. * Get all of the sections for a given name.
  93. *
  94. * @param string $name
  95. *
  96. * @return array
  97. */
  98. public function getSections(string $name)
  99. {
  100. return $this->sortSections($name);
  101. }
  102. /**
  103. * Sort the listeners for a given event by priority.
  104. *
  105. * @param string $name
  106. *
  107. * @return array
  108. */
  109. protected function sortSections(string $name)
  110. {
  111. if (empty($this->sections[$name])) {
  112. return [];
  113. }
  114. krsort($this->sections[$name]);
  115. return call_user_func_array(
  116. 'array_merge',
  117. $this->sections[$name]
  118. );
  119. }
  120. /**
  121. * Check if section exists.
  122. *
  123. * @param string $name
  124. *
  125. * @return bool
  126. */
  127. public function hasSection(string $name)
  128. {
  129. return array_key_exists($name, $this->sections);
  130. }
  131. /**
  132. * Check if default section exists.
  133. *
  134. * @param string $name
  135. *
  136. * @return bool
  137. */
  138. public function hasDefaultSection(string $name)
  139. {
  140. return array_key_exists($name, $this->defaultSections);
  141. }
  142. /**
  143. * @param string $name
  144. * @param mixed $content
  145. * @param array $options
  146. *
  147. * @return string
  148. */
  149. protected function resolveContent(string $name, &$content, array &$options)
  150. {
  151. if (is_string($content)) {
  152. return $content;
  153. }
  154. if (! is_array($content)) {
  155. $content = [['append' => true, 'value' => $content]];
  156. }
  157. $options = new Fluent($options);
  158. $options->previous = '';
  159. $result = '';
  160. foreach ($content as &$item) {
  161. $value = Helper::render($item['value'] ?? '', [$options]);
  162. $append = $item['append'] ?? false;
  163. if (! $append) {
  164. $result = '';
  165. }
  166. $result .= $value;
  167. $options->previous = $result;
  168. }
  169. // $this->sections[$name] = [['value' => &$result]];
  170. return $result;
  171. }
  172. /**
  173. * Flush all of the sections.
  174. *
  175. * @return void
  176. */
  177. public function flushSections()
  178. {
  179. $this->sections = [];
  180. $this->defaultSections = [];
  181. }
  182. }