You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
4.7 KiB
202 lines
4.7 KiB
<?php |
|
|
|
namespace Dcat\Admin\Layout; |
|
|
|
use Dcat\Admin\Exception\RuntimeException; |
|
use Dcat\Admin\Support\Helper; |
|
use Illuminate\Contracts\Support\Htmlable; |
|
use Illuminate\Contracts\Support\Renderable; |
|
use Illuminate\Support\Fluent; |
|
|
|
class SectionManager |
|
{ |
|
/** |
|
* All of the finished, captured sections. |
|
* |
|
* @var array |
|
*/ |
|
protected $sections = []; |
|
|
|
/** |
|
* @var array |
|
*/ |
|
protected $defaultSections = []; |
|
|
|
/** |
|
* Inject content into a section. |
|
* |
|
* @param string $section |
|
* @param string|Renderable|Htmlable|callable $content |
|
* @param bool $append |
|
* @param int $priority |
|
* @return void |
|
*/ |
|
public function inject($section, $content, bool $append = true, int $priority = 10) |
|
{ |
|
$this->put($section, $content, $append, $priority); |
|
} |
|
|
|
/** |
|
* @param string $section |
|
* @param string|Renderable|Htmlable|callable $content |
|
* @return void |
|
*/ |
|
public function injectDefault(string $section, $content) |
|
{ |
|
if ($this->hasSection($section)) { |
|
return; |
|
} |
|
|
|
$this->defaultSections[$section] = &$content; |
|
} |
|
|
|
/** |
|
* Set content to a given section. |
|
* |
|
* @param string $section |
|
* @param string|Renderable|Htmlable|callable $content |
|
* @param bool $append |
|
* @param int $priority |
|
* @return void |
|
*/ |
|
protected function put(string $section, $content, bool $append = false, int $priority = 10) |
|
{ |
|
if (! $section) { |
|
throw new RuntimeException('Section name is required.'); |
|
} |
|
|
|
if (! isset($this->sections[$section])) { |
|
unset($this->defaultSections[$section]); |
|
|
|
$this->sections[$section] = []; |
|
} |
|
|
|
if (! isset($this->sections[$section][$priority])) { |
|
$this->sections[$section][$priority] = []; |
|
} |
|
|
|
$this->sections[$section][$priority][] = [ |
|
'append' => $append, |
|
'value' => &$content, |
|
]; |
|
} |
|
|
|
/** |
|
* Get the string contents of a section. |
|
* |
|
* @param string $section |
|
* @param mixed $default |
|
* @param array $options |
|
* @return string |
|
*/ |
|
public function yieldContent(string $section, $default = '', array $options = []) |
|
{ |
|
$defaultSection = $this->defaultSections[$section] ?? null; |
|
|
|
if (! $this->hasSection($section) && $defaultSection === null) { |
|
return Helper::render($default, [new Fluent()]); |
|
} |
|
|
|
$content = $this->getSections($section) ?: $defaultSection; |
|
|
|
return $this->resolveContent($section, $content, $options); |
|
} |
|
|
|
/** |
|
* Get all of the sections for a given name. |
|
* |
|
* @param string $name |
|
* @return array |
|
*/ |
|
public function getSections(string $name) |
|
{ |
|
return $this->sortSections($name); |
|
} |
|
|
|
/** |
|
* Sort the listeners for a given event by priority. |
|
* |
|
* @param string $name |
|
* @return array |
|
*/ |
|
protected function sortSections(string $name) |
|
{ |
|
if (empty($this->sections[$name])) { |
|
return []; |
|
} |
|
krsort($this->sections[$name]); |
|
|
|
return call_user_func_array( |
|
'array_merge', |
|
$this->sections[$name] |
|
); |
|
} |
|
|
|
/** |
|
* Check if section exists. |
|
* |
|
* @param string $name |
|
* @return bool |
|
*/ |
|
public function hasSection(string $name) |
|
{ |
|
return array_key_exists($name, $this->sections); |
|
} |
|
|
|
/** |
|
* Check if default section exists. |
|
* |
|
* @param string $name |
|
* @return bool |
|
*/ |
|
public function hasDefaultSection(string $name) |
|
{ |
|
return array_key_exists($name, $this->defaultSections); |
|
} |
|
|
|
/** |
|
* @param string $name |
|
* @param mixed $content |
|
* @param array $options |
|
* @return string |
|
*/ |
|
protected function resolveContent(string $name, &$content, array &$options) |
|
{ |
|
if (is_string($content)) { |
|
return $content; |
|
} |
|
|
|
if (! is_array($content)) { |
|
$content = [['append' => true, 'value' => $content]]; |
|
} |
|
|
|
$options = new Fluent($options); |
|
|
|
$options->previous = ''; |
|
|
|
$result = ''; |
|
foreach ($content as &$item) { |
|
$value = Helper::render($item['value'] ?? '', [$options]); |
|
$append = $item['append'] ?? false; |
|
|
|
if (! $append) { |
|
$result = ''; |
|
} |
|
$result .= $value; |
|
$options->previous = $result; |
|
} |
|
|
|
return $result; |
|
} |
|
|
|
/** |
|
* Flush all of the sections. |
|
* |
|
* @return void |
|
*/ |
|
public function flushSections() |
|
{ |
|
$this->sections = []; |
|
$this->defaultSections = []; |
|
} |
|
}
|
|
|