Started backend theme system
Allows customization of back-end components via event-driven handling from the theme folder.
This commit is contained in:
parent
1420f239fc
commit
c61c3bc608
7 changed files with 142 additions and 0 deletions
|
@ -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,
|
||||
|
||||
],
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
16
app/Facades/Theme.php
Normal file
16
app/Facades/Theme.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php namespace BookStack\Facades;
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
class Theme extends Facade
|
||||
{
|
||||
/**
|
||||
* Get the registered name of the component.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function getFacadeAccessor()
|
||||
{
|
||||
return 'theme';
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ namespace BookStack\Providers;
|
|||
use BookStack\Actions\ActivityService;
|
||||
use BookStack\Actions\ViewService;
|
||||
use BookStack\Auth\Permissions\PermissionService;
|
||||
use BookStack\Theming\ThemeService;
|
||||
use BookStack\Uploads\ImageService;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
|
@ -42,5 +43,9 @@ class CustomFacadeProvider extends ServiceProvider
|
|||
$this->app->singleton('permissions', function () {
|
||||
return $this->app->make(PermissionService::class);
|
||||
});
|
||||
|
||||
$this->app->singleton('theme', function () {
|
||||
return $this->app->make(ThemeService::class);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
34
app/Providers/ThemeServiceProvider.php
Normal file
34
app/Providers/ThemeServiceProvider.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace BookStack\Providers;
|
||||
|
||||
use BookStack\Theming\ThemeEvents;
|
||||
use BookStack\Theming\ThemeService;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class ThemeServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->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);
|
||||
}
|
||||
}
|
32
app/Theming/ThemeEvents.php
Normal file
32
app/Theming/ThemeEvents.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php namespace BookStack\Theming;
|
||||
|
||||
/**
|
||||
* The ThemeEvents used within BookStack.
|
||||
*
|
||||
* This file details the events that BookStack may fire via the custom
|
||||
* theme system, including event names, parameters and expected return types.
|
||||
*
|
||||
* This system is regarded as semi-stable.
|
||||
* We'll look to fix issues with it or migrate old event types but
|
||||
* events and their signatures may change in new versions of BookStack.
|
||||
* We'd advise testing any usage of these events upon upgrade.
|
||||
*/
|
||||
class ThemeEvents
|
||||
{
|
||||
/**
|
||||
* Application boot-up.
|
||||
* After main services are registered.
|
||||
* @param \BookStack\Application $app
|
||||
*/
|
||||
const APP_BOOT = 'app_boot';
|
||||
|
||||
/**
|
||||
* Commonmark environment configure.
|
||||
* Provides the commonmark library environment for customization
|
||||
* before its used to render markdown content.
|
||||
* If the listener returns a non-null value, that will be used as an environment instead.
|
||||
* @param \League\CommonMark\ConfigurableEnvironmentInterface $environment
|
||||
* @returns \League\CommonMark\ConfigurableEnvironmentInterface|null
|
||||
*/
|
||||
const COMMONMARK_ENVIRONMENT_CONFIGURE = 'commonmark_environment_configure';
|
||||
}
|
50
app/Theming/ThemeService.php
Normal file
50
app/Theming/ThemeService.php
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php namespace BookStack\Theming;
|
||||
|
||||
class ThemeService
|
||||
{
|
||||
protected $listeners = [];
|
||||
|
||||
/**
|
||||
* Listen to a given custom theme event,
|
||||
* setting up the action to be ran when the event occurs.
|
||||
*/
|
||||
public function listen(string $event, callable $action)
|
||||
{
|
||||
if (!isset($this->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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue