Files
ABSDEV/Modules/Stylist/Http/Controllers/ThemeManagementController.php
T
Mark Gregory a433897538 Implemented the dynamic theme manager and merged the supplied themes.
Included

* Standardised all six theme.json files to manifest version 2:
    * admin
    * common
    * corporate
    * saasland
    * swiss
    * welcome
* Every manifest now uses the same fields and structure.
* Separate active frontend and backend themes.
* One-click theme activation.
* Theme preview in a new browser tab without activating it.
* Theme cards showing:
    * Preview
    * Name
    * Version
    * Author
    * Description
    * Theme type
    * Active status
* Dynamic theme-specific settings.
* Support for:
    * Text
    * URL
    * Colour
    * Textarea
    * Checkbox fields
    * Variants
    * Appearance
    * Accent palettes
* Theme ZIP installation.
* Theme ZIP export.
* Asset optimisation.
* Accessibility validation.
* Safe ZIP path validation.
* Theme inheritance.
* Active themes cannot be uninstalled.
* Parent themes cannot be uninstalled while child themes depend on them.
* Stylist administration routes now require an authenticated, verified user.
* Manifest validation now restricts theme types to:
    * frontend
    * backend
    * common
* Added activation tests for independent frontend and backend theme selection.

The supplied corporate theme was incomplete, so I added the required backend entry view and placeholder asset files while preserving its supplied layout.
2026-07-28 12:54:10 +01:00

88 lines
3.0 KiB
PHP

<?php
namespace Modules\Stylist\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\Settings\Services\SettingsRepository;
use Modules\Stylist\Services\ThemeAccessibilityValidator;
use Modules\Stylist\Services\ThemeOptimizer;
use Modules\Stylist\Services\ThemePackageManager;
use Modules\Stylist\Services\ThemeSettings;
use Modules\Stylist\Theme\Loader;
use Modules\Stylist\View\ThemeViewResolver;
final class ThemeManagementController extends Controller
{
public function activate(string $theme, Loader $loader, SettingsRepository $settings)
{
$item = $loader->find($theme);
abort_unless(in_array($item->type(), ['frontend', 'backend'], true), 422, 'Only frontend and backend themes can be activated.');
$settings->put($item->type().'_theme', $item->key(), 'site', 'string', true);
return back()->with('status', $item->name().' is now the active '.$item->type().' theme.');
}
public function preview(string $theme, Loader $loader, ThemeViewResolver $views)
{
$item = $loader->find($theme);
return $views->makeForTheme($item->key(), $item->entryView(), [
'themePreview' => true,
'previewTheme' => $item,
]);
}
public function settings(Request $request, string $theme, Loader $loader, ThemeSettings $settings)
{
$item = $loader->find($theme);
$settings->save(
$item,
(array) $request->input('settings', []),
(string) $request->input('variant', 'light'),
$request->string('appearance')->toString() ?: null,
$request->string('accent')->toString() ?: null,
);
return back()->with('status', 'Theme settings saved.');
}
public function install(Request $request, ThemePackageManager $packages)
{
$request->validate(['theme' => ['required', 'file', 'mimes:zip', 'max:51200']]);
$theme = $packages->install($request->file('theme'));
return back()->with('status', $theme->name().' installed.');
}
public function uninstall(string $theme, Loader $loader, ThemePackageManager $packages)
{
$item = $loader->find($theme);
$packages->uninstall($item);
return back()->with('status', $item->name().' uninstalled.');
}
public function export(string $theme, Loader $loader, ThemePackageManager $packages)
{
$item = $loader->find($theme);
$path = $packages->export($item);
return response()->download($path)->deleteFileAfterSend();
}
public function optimize(string $theme, Loader $loader, ThemeOptimizer $optimizer)
{
$item = $loader->find($theme);
$result = $optimizer->optimize($item);
return back()->with('status', "Optimised {$result['css']} CSS, {$result['js']} JS and {$result['images']} images.");
}
public function validateTheme(string $theme, Loader $loader, ThemeAccessibilityValidator $validator)
{
return response()->json(['issues' => $validator->validate($loader->find($theme))]);
}
}