New Branch Structure
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Stylist\View;
|
||||
|
||||
use Illuminate\Contracts\View\Factory as ViewFactory;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Modules\Stylist\Theme\Exceptions\ThemeNotFoundException;
|
||||
use Modules\Stylist\Theme\Loader;
|
||||
use Modules\Stylist\Theme\Stylist;
|
||||
use RuntimeException;
|
||||
|
||||
final class ThemeViewResolver
|
||||
{
|
||||
/** @var array<string, array<int, string>> */
|
||||
private array $candidateCache = [];
|
||||
|
||||
public function __construct(
|
||||
private readonly Stylist $stylist,
|
||||
private readonly ViewFactory $views,
|
||||
private readonly Loader $loader,
|
||||
) {}
|
||||
|
||||
public function make(string $view, array $data = [], array $mergeData = []): View
|
||||
{
|
||||
return $this->views->first(
|
||||
$this->candidates($view),
|
||||
array_replace([
|
||||
'themeSettings' => $this->stylist->settings(),
|
||||
'themeVariant' => $this->stylist->variant(),
|
||||
], $data),
|
||||
$mergeData,
|
||||
);
|
||||
}
|
||||
|
||||
public function makeForTheme(string $theme, string $view, array $data = [], array $mergeData = []): View
|
||||
{
|
||||
return $this->views->first($this->candidatesForTheme($theme, $view), $data, $mergeData);
|
||||
}
|
||||
|
||||
/** @return array<int, string> */
|
||||
public function candidates(string $view): array
|
||||
{
|
||||
return $this->candidatesForTheme($this->stylist->current()->key(), $view);
|
||||
}
|
||||
|
||||
/** @return array<int, string> */
|
||||
public function candidatesForTheme(string $theme, string $view): array
|
||||
{
|
||||
$view = ltrim($view, '.');
|
||||
$cacheKey = $theme.'|'.$view;
|
||||
|
||||
if (isset($this->candidateCache[$cacheKey])) {
|
||||
return $this->candidateCache[$cacheKey];
|
||||
}
|
||||
|
||||
$keys = $this->inheritanceChain($theme);
|
||||
$fallback = (string) config('stylist.default_theme', 'common');
|
||||
|
||||
if ($fallback !== '' && ! in_array($fallback, $keys, true)) {
|
||||
try {
|
||||
$keys = array_merge($keys, $this->inheritanceChain($fallback));
|
||||
} catch (ThemeNotFoundException) {
|
||||
// A missing configured fallback is diagnosed by stylist:doctor.
|
||||
}
|
||||
}
|
||||
|
||||
if (! in_array('common', $keys, true)) {
|
||||
try {
|
||||
$keys = array_merge($keys, $this->inheritanceChain('common'));
|
||||
} catch (ThemeNotFoundException) {
|
||||
// The module fallback below remains available.
|
||||
}
|
||||
}
|
||||
|
||||
$candidates = [];
|
||||
foreach (array_values(array_unique($keys)) as $key) {
|
||||
$this->registerNamespace($key);
|
||||
$candidates[] = "stylist-theme-{$key}::{$view}";
|
||||
$candidates[] = "stylist-module-theme-{$key}::{$view}";
|
||||
}
|
||||
|
||||
$candidates[] = "stylist::{$view}";
|
||||
$candidates[] = $view;
|
||||
|
||||
return $this->candidateCache[$cacheKey] = array_values(array_unique($candidates));
|
||||
}
|
||||
|
||||
public function flush(): void
|
||||
{
|
||||
$this->candidateCache = [];
|
||||
}
|
||||
|
||||
/** @return array<int, string> */
|
||||
private function inheritanceChain(string $theme): array
|
||||
{
|
||||
$keys = [];
|
||||
$seen = [];
|
||||
$key = $theme;
|
||||
|
||||
while ($key !== '') {
|
||||
if (isset($seen[$key])) {
|
||||
throw new RuntimeException('Theme inheritance cycle detected at ['.$key.'].');
|
||||
}
|
||||
|
||||
$seen[$key] = true;
|
||||
$loaded = $this->loader->find($key);
|
||||
$keys[] = $loaded->key();
|
||||
$key = $loaded->parent() ?? '';
|
||||
}
|
||||
|
||||
return $keys;
|
||||
}
|
||||
|
||||
private function registerNamespace(string $theme): void
|
||||
{
|
||||
try {
|
||||
$loaded = $this->loader->find($theme);
|
||||
} catch (ThemeNotFoundException) {
|
||||
return;
|
||||
}
|
||||
|
||||
$viewsPath = $loaded->path().DIRECTORY_SEPARATOR.'views';
|
||||
if (! is_dir($viewsPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->views->addNamespace("stylist-theme-{$theme}", $viewsPath);
|
||||
$this->views->addNamespace("stylist-module-theme-{$theme}", $viewsPath);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user