84 lines
2.0 KiB
PHP
Executable File
84 lines
2.0 KiB
PHP
Executable File
<?php
|
|
|
|
namespace Modules\Stylist\Theme;
|
|
|
|
use Illuminate\Filesystem\Filesystem;
|
|
use Illuminate\Support\Collection;
|
|
use Modules\Stylist\Theme\Exceptions\ThemeNotFoundException;
|
|
|
|
final class Loader
|
|
{
|
|
private ?Collection $themes = null;
|
|
|
|
public function __construct(
|
|
private readonly Filesystem $files,
|
|
private readonly Json $json,
|
|
private readonly ManifestValidator $validator,
|
|
) {}
|
|
|
|
public function all(): Collection
|
|
{
|
|
if ($this->themes !== null) {
|
|
return $this->themes;
|
|
}
|
|
|
|
$themes = collect();
|
|
|
|
foreach ($this->roots() as $root) {
|
|
if (! $this->files->isDirectory($root)) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($this->files->directories($root) as $themePath) {
|
|
try {
|
|
$theme = $this->fromPath($themePath);
|
|
$themes->put($theme->key(), $theme);
|
|
} catch (\Throwable $exception) {
|
|
report($exception);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $this->themes = $themes->sortKeys();
|
|
}
|
|
|
|
public function find(string $key): Theme
|
|
{
|
|
$theme = $this->all()->get($key);
|
|
|
|
if (! $theme) {
|
|
throw ThemeNotFoundException::forKey($key);
|
|
}
|
|
|
|
return $theme;
|
|
}
|
|
|
|
public function fromPath(string $path): Theme
|
|
{
|
|
$data = $this->validator->validate($this->json->read($path), $path);
|
|
|
|
return new Theme(
|
|
key: $data['key'],
|
|
name: $data['name'],
|
|
path: rtrim($path, DIRECTORY_SEPARATOR),
|
|
stylesheet: $data['stylesheet'],
|
|
script: $data['script'],
|
|
variables: $data['variables'],
|
|
meta: $data,
|
|
);
|
|
}
|
|
|
|
public function flush(): void
|
|
{
|
|
$this->themes = null;
|
|
}
|
|
|
|
/** @return array<int, string> */
|
|
public function roots(): array
|
|
{
|
|
return array_values(array_unique(array_filter([
|
|
(string) config('stylist.themes_path'),
|
|
])));
|
|
}
|
|
}
|