Просмотр файла vendor/laravel/framework/src/Illuminate/View/Concerns/ManagesComponents.php

Размер файла: 3.9Kb
  1. <?php
  2.  
  3. namespace Illuminate\View\Concerns;
  4.  
  5. use Illuminate\Contracts\Support\Htmlable;
  6. use Illuminate\Contracts\View\View;
  7. use Illuminate\Support\Arr;
  8. use Illuminate\Support\HtmlString;
  9. use InvalidArgumentException;
  10.  
  11. trait ManagesComponents
  12. {
  13. /**
  14. * The components being rendered.
  15. *
  16. * @var array
  17. */
  18. protected $componentStack = [];
  19.  
  20. /**
  21. * The original data passed to the component.
  22. *
  23. * @var array
  24. */
  25. protected $componentData = [];
  26.  
  27. /**
  28. * The slot contents for the component.
  29. *
  30. * @var array
  31. */
  32. protected $slots = [];
  33.  
  34. /**
  35. * The names of the slots being rendered.
  36. *
  37. * @var array
  38. */
  39. protected $slotStack = [];
  40.  
  41. /**
  42. * Start a component rendering process.
  43. *
  44. * @param \Illuminate\Contracts\View\View|\Illuminate\Contracts\Support\Htmlable|\Closure|string $view
  45. * @param array $data
  46. * @return void
  47. */
  48. public function startComponent($view, array $data = [])
  49. {
  50. if (ob_start()) {
  51. $this->componentStack[] = $view;
  52.  
  53. $this->componentData[$this->currentComponent()] = $data;
  54.  
  55. $this->slots[$this->currentComponent()] = [];
  56. }
  57. }
  58.  
  59. /**
  60. * Get the first view that actually exists from the given list, and start a component.
  61. *
  62. * @param array $names
  63. * @param array $data
  64. * @return void
  65. */
  66. public function startComponentFirst(array $names, array $data = [])
  67. {
  68. $name = Arr::first($names, function ($item) {
  69. return $this->exists($item);
  70. });
  71.  
  72. $this->startComponent($name, $data);
  73. }
  74.  
  75. /**
  76. * Render the current component.
  77. *
  78. * @return string
  79. */
  80. public function renderComponent()
  81. {
  82. $view = array_pop($this->componentStack);
  83.  
  84. $data = $this->componentData();
  85.  
  86. $view = value($view, $data);
  87.  
  88. if ($view instanceof View) {
  89. return $view->with($data)->render();
  90. } elseif ($view instanceof Htmlable) {
  91. return $view->toHtml();
  92. } else {
  93. return $this->make($view, $data)->render();
  94. }
  95. }
  96.  
  97. /**
  98. * Get the data for the given component.
  99. *
  100. * @return array
  101. */
  102. protected function componentData()
  103. {
  104. $defaultSlot = new HtmlString(trim(ob_get_clean()));
  105.  
  106. $slots = array_merge([
  107. '__default' => $defaultSlot,
  108. ], $this->slots[count($this->componentStack)]);
  109.  
  110. return array_merge(
  111. $this->componentData[count($this->componentStack)],
  112. ['slot' => $defaultSlot],
  113. $this->slots[count($this->componentStack)],
  114. ['__laravel_slots' => $slots]
  115. );
  116. }
  117.  
  118. /**
  119. * Start the slot rendering process.
  120. *
  121. * @param string $name
  122. * @param string|null $content
  123. * @return void
  124. *
  125. * @throws \InvalidArgumentException
  126. */
  127. public function slot($name, $content = null)
  128. {
  129. if (func_num_args() > 2) {
  130. throw new InvalidArgumentException('You passed too many arguments to the ['.$name.'] slot.');
  131. } elseif (func_num_args() === 2) {
  132. $this->slots[$this->currentComponent()][$name] = $content;
  133. } elseif (ob_start()) {
  134. $this->slots[$this->currentComponent()][$name] = '';
  135.  
  136. $this->slotStack[$this->currentComponent()][] = $name;
  137. }
  138. }
  139.  
  140. /**
  141. * Save the slot content for rendering.
  142. *
  143. * @return void
  144. */
  145. public function endSlot()
  146. {
  147. last($this->componentStack);
  148.  
  149. $currentSlot = array_pop(
  150. $this->slotStack[$this->currentComponent()]
  151. );
  152.  
  153. $this->slots[$this->currentComponent()][$currentSlot] = new HtmlString(trim(ob_get_clean()));
  154. }
  155.  
  156. /**
  157. * Get the index for the current component.
  158. *
  159. * @return int
  160. */
  161. protected function currentComponent()
  162. {
  163. return count($this->componentStack) - 1;
  164. }
  165. }