From c61c3bc60890f171589f3fcdccbe217c900af1c1 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 16 Mar 2021 17:14:03 +0000 Subject: [PATCH] Started backend theme system Allows customization of back-end components via event-driven handling from the theme folder. --- app/Config/app.php | 2 ++ app/Entities/Tools/PageContent.php | 3 ++ app/Facades/Theme.php | 16 +++++++++ app/Providers/CustomFacadeProvider.php | 5 +++ app/Providers/ThemeServiceProvider.php | 34 ++++++++++++++++++ app/Theming/ThemeEvents.php | 32 +++++++++++++++++ app/Theming/ThemeService.php | 50 ++++++++++++++++++++++++++ 7 files changed, 142 insertions(+) create mode 100644 app/Facades/Theme.php create mode 100644 app/Providers/ThemeServiceProvider.php create mode 100644 app/Theming/ThemeEvents.php create mode 100644 app/Theming/ThemeService.php diff --git a/app/Config/app.php b/app/Config/app.php index 741c7fd19..065845f96 100755 --- a/app/Config/app.php +++ b/app/Config/app.php @@ -115,6 +115,7 @@ return [ BookStack\Providers\TranslationServiceProvider::class, // BookStack custom service providers + BookStack\Providers\ThemeServiceProvider::class, BookStack\Providers\AuthServiceProvider::class, BookStack\Providers\AppServiceProvider::class, BookStack\Providers\BroadcastServiceProvider::class, @@ -186,6 +187,7 @@ return [ 'Views' => BookStack\Facades\Views::class, 'Images' => BookStack\Facades\Images::class, 'Permissions' => BookStack\Facades\Permissions::class, + 'Theme' => BookStack\Facades\Theme::class, ], diff --git a/app/Entities/Tools/PageContent.php b/app/Entities/Tools/PageContent.php index 62982f4ad..82499cdf2 100644 --- a/app/Entities/Tools/PageContent.php +++ b/app/Entities/Tools/PageContent.php @@ -2,6 +2,8 @@ use BookStack\Entities\Models\Page; use BookStack\Entities\Tools\Markdown\CustomStrikeThroughExtension; +use BookStack\Facades\Theme; +use BookStack\Theming\ThemeEvents; use DOMDocument; use DOMNodeList; use DOMXPath; @@ -53,6 +55,7 @@ class PageContent $environment->addExtension(new TableExtension()); $environment->addExtension(new TaskListExtension()); $environment->addExtension(new CustomStrikeThroughExtension()); + $environment = Theme::dispatch(ThemeEvents::COMMONMARK_ENVIRONMENT_CONFIGURE, $environment) ?? $environment; $converter = new CommonMarkConverter([], $environment); return $converter->convertToHtml($markdown); } diff --git a/app/Facades/Theme.php b/app/Facades/Theme.php new file mode 100644 index 000000000..9b96e2ed2 --- /dev/null +++ b/app/Facades/Theme.php @@ -0,0 +1,16 @@ +app->singleton('permissions', function () { return $this->app->make(PermissionService::class); }); + + $this->app->singleton('theme', function () { + return $this->app->make(ThemeService::class); + }); } } diff --git a/app/Providers/ThemeServiceProvider.php b/app/Providers/ThemeServiceProvider.php new file mode 100644 index 000000000..c41a15af0 --- /dev/null +++ b/app/Providers/ThemeServiceProvider.php @@ -0,0 +1,34 @@ +app->singleton(ThemeService::class, function ($app) { + return new ThemeService; + }); + } + + /** + * Bootstrap services. + * + * @return void + */ + public function boot() + { + $themeService = $this->app->make(ThemeService::class); + $themeService->readThemeActions(); + $themeService->dispatch(ThemeEvents::APP_BOOT, $this->app); + } +} diff --git a/app/Theming/ThemeEvents.php b/app/Theming/ThemeEvents.php new file mode 100644 index 000000000..753b13d91 --- /dev/null +++ b/app/Theming/ThemeEvents.php @@ -0,0 +1,32 @@ +listeners[$event])) { + $this->listeners[$event] = []; + } + + $this->listeners[$event][] = $action; + } + + /** + * Dispatch the given event name. + * Runs any registered listeners for that event name, + * passing all additional variables to the listener action. + * + * If a callback returns a non-null value, this method will + * stop and return that value itself. + * @return mixed + */ + public function dispatch(string $event, ...$args) + { + foreach ($this->listeners[$event] ?? [] as $action) { + $result = call_user_func_array($action, $args); + if (!is_null($result)) { + return $result; + } + } + return null; + } + + /** + * Read any actions from the set theme path if the 'functions.php' file exists. + */ + public function readThemeActions() + { + $themeActionsFile = theme_path('functions.php'); + if (file_exists($themeActionsFile)) { + require $themeActionsFile; + } + } +} \ No newline at end of file