updaetd deployer
This commit is contained in:
@@ -5,7 +5,6 @@ declare(strict_types=1);
|
||||
namespace Modules\Helpdesk\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
@@ -136,14 +135,19 @@ final class HelpdeskServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected function registerViews(): void
|
||||
{
|
||||
$viewPath = resource_path('views/modules/'.ModuleInfo::nameLower());
|
||||
$sourcePath = module_path(ModuleInfo::name(), 'Resources/views');
|
||||
$themeRoot = rtrim((string) config('stylist.themes_path', resource_path('themes')), DIRECTORY_SEPARATOR);
|
||||
$backendTheme = (string) config('stylist.default_backend_theme', 'backend');
|
||||
$viewPath = $themeRoot.DIRECTORY_SEPARATOR.$backendTheme
|
||||
.DIRECTORY_SEPARATOR.'views'.DIRECTORY_SEPARATOR.'modules'.DIRECTORY_SEPARATOR.ModuleInfo::nameLower();
|
||||
|
||||
// Module source views remain module-owned. Any application override is
|
||||
// published into the selected backend theme, never resources/views.
|
||||
$this->publishes([
|
||||
$sourcePath => $viewPath,
|
||||
], ['views', ModuleInfo::nameLower().'-module-views']);
|
||||
|
||||
$this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), ModuleInfo::nameLower());
|
||||
$this->loadViewsFrom($sourcePath, ModuleInfo::nameLower());
|
||||
|
||||
Blade::componentNamespace('Modules\Helpdesk\View\Components', 'helpdesk');
|
||||
Blade::anonymousComponentPath($sourcePath.'/components', 'helpdesk');
|
||||
@@ -165,24 +169,6 @@ final class HelpdeskServiceProvider extends ServiceProvider
|
||||
$this->loadTranslationsFrom(module_path(ModuleInfo::name(), 'Resources/lang'), ModuleInfo::nameLower());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get publishable view override paths.
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
private function getPublishableViewPaths(): array
|
||||
{
|
||||
$paths = [];
|
||||
|
||||
foreach (Config::get('view.paths') as $path) {
|
||||
if (is_dir($path.'/modules/'.ModuleInfo::nameLower())) {
|
||||
$paths[] = $path.'/modules/'.ModuleInfo::nameLower();
|
||||
}
|
||||
}
|
||||
|
||||
return $paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get provided services.
|
||||
*
|
||||
|
||||
@@ -73,6 +73,7 @@ final class StylistServiceProvider extends ServiceProvider
|
||||
|
||||
$this->app->booted(function (): void {
|
||||
$this->registerSelectedThemeOverrides();
|
||||
$this->registerSelectedThemeFluxOverrides();
|
||||
});
|
||||
|
||||
}
|
||||
@@ -218,7 +219,14 @@ final class StylistServiceProvider extends ServiceProvider
|
||||
// boot order and incremental prependLocation() calls. Theme paths stay first;
|
||||
// Laravel's normal view locations remain as the final fallback.
|
||||
if (method_exists($finder, 'getPaths') && method_exists($finder, 'setPaths')) {
|
||||
$existingPaths = $finder->getPaths();
|
||||
// The application intentionally has no resources/views tree. Laravel's
|
||||
// default FileViewFinder still starts with that location, and view:cache
|
||||
// asks Symfony Finder to scan every registered path. Remove missing legacy
|
||||
// locations so theme-only applications can be optimized on a clean release.
|
||||
$existingPaths = array_values(array_filter(
|
||||
$finder->getPaths(),
|
||||
static fn (string $path): bool => is_dir($path),
|
||||
));
|
||||
$paths = array_values(array_unique(array_merge($themePaths, $existingPaths)));
|
||||
$finder->setPaths($paths);
|
||||
|
||||
@@ -236,6 +244,78 @@ final class StylistServiceProvider extends ServiceProvider
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make Flux application overrides theme-owned.
|
||||
*
|
||||
* Flux normally discovers custom components from resources/views/flux. This
|
||||
* application deliberately has no resources/views tree, so expose the selected
|
||||
* theme's views/flux directory through Flux's existing view namespace instead.
|
||||
* Package-provided Flux views remain available as the final fallback.
|
||||
*/
|
||||
private function registerSelectedThemeFluxOverrides(): void
|
||||
{
|
||||
$stylist = $this->app->make(Stylist::class);
|
||||
$orderedThemes = [$stylist->current(), $stylist->frontend(), $stylist->backend()];
|
||||
$keys = [];
|
||||
|
||||
foreach ($orderedThemes as $theme) {
|
||||
foreach ($this->themeChain($theme) as $key) {
|
||||
if (! in_array($key, $keys, true)) {
|
||||
$keys[] = $key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! in_array('common', $keys, true)) {
|
||||
$keys[] = 'common';
|
||||
}
|
||||
|
||||
$themeFluxPaths = [];
|
||||
|
||||
foreach ($keys as $key) {
|
||||
try {
|
||||
$theme = $this->app->make(Loader::class)->find($key);
|
||||
} catch (\Throwable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fluxPath = $theme->path().DIRECTORY_SEPARATOR.'views'.DIRECTORY_SEPARATOR.'flux';
|
||||
|
||||
if (is_dir($fluxPath)) {
|
||||
$themeFluxPaths[] = $fluxPath;
|
||||
}
|
||||
}
|
||||
|
||||
if ($themeFluxPaths === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
$finder = View::getFinder();
|
||||
|
||||
if (! method_exists($finder, 'getHints')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$hints = $finder->getHints();
|
||||
$existingFluxPaths = array_values(array_filter(
|
||||
(array) ($hints['flux'] ?? []),
|
||||
static fn (string $path): bool => is_dir($path),
|
||||
));
|
||||
$paths = array_values(array_unique(array_merge($themeFluxPaths, $existingFluxPaths)));
|
||||
|
||||
if (method_exists($finder, 'replaceNamespace')) {
|
||||
$finder->replaceNamespace('flux', $paths);
|
||||
} else {
|
||||
foreach (array_reverse($themeFluxPaths) as $fluxPath) {
|
||||
View::prependNamespace('flux', $fluxPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (method_exists($finder, 'flush')) {
|
||||
$finder->flush();
|
||||
}
|
||||
}
|
||||
|
||||
/** @return array<int, string> */
|
||||
private function themeChain(Theme $theme): array
|
||||
{
|
||||
|
||||
@@ -42,4 +42,23 @@ final class WelcomeThemeViewTest extends TestCase
|
||||
$this->assertFileExists(resource_path('themes/backend/assets/css/app.css'));
|
||||
$this->assertFileExists(resource_path('themes/backend/assets/js/passkeys.js'));
|
||||
}
|
||||
|
||||
public function test_view_finder_contains_only_existing_application_view_locations(): void
|
||||
{
|
||||
foreach (view()->getFinder()->getPaths() as $path) {
|
||||
$this->assertDirectoryExists($path);
|
||||
}
|
||||
}
|
||||
|
||||
public function test_backend_flux_icon_overrides_are_owned_by_the_backend_theme(): void
|
||||
{
|
||||
$this->assertTrue(view()->exists('flux::icon.folder-git-2'));
|
||||
$this->assertTrue(view()->exists('flux::icon.book-open-text'));
|
||||
$this->assertTrue(view()->exists('flux::icon.chevrons-up-down'));
|
||||
|
||||
$this->assertStringContainsString(
|
||||
resource_path('themes/backend/views/flux/icon/folder-git-2.blade.php'),
|
||||
view('flux::icon.folder-git-2')->getPath(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user