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\Providers\TranslationServiceProvider::class,
|
||||||
|
|
||||||
// BookStack custom service providers
|
// BookStack custom service providers
|
||||||
|
BookStack\Providers\ThemeServiceProvider::class,
|
||||||
BookStack\Providers\AuthServiceProvider::class,
|
BookStack\Providers\AuthServiceProvider::class,
|
||||||
BookStack\Providers\AppServiceProvider::class,
|
BookStack\Providers\AppServiceProvider::class,
|
||||||
BookStack\Providers\BroadcastServiceProvider::class,
|
BookStack\Providers\BroadcastServiceProvider::class,
|
||||||
|
@ -186,6 +187,7 @@ return [
|
||||||
'Views' => BookStack\Facades\Views::class,
|
'Views' => BookStack\Facades\Views::class,
|
||||||
'Images' => BookStack\Facades\Images::class,
|
'Images' => BookStack\Facades\Images::class,
|
||||||
'Permissions' => BookStack\Facades\Permissions::class,
|
'Permissions' => BookStack\Facades\Permissions::class,
|
||||||
|
'Theme' => BookStack\Facades\Theme::class,
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
use BookStack\Entities\Models\Page;
|
use BookStack\Entities\Models\Page;
|
||||||
use BookStack\Entities\Tools\Markdown\CustomStrikeThroughExtension;
|
use BookStack\Entities\Tools\Markdown\CustomStrikeThroughExtension;
|
||||||
|
use BookStack\Facades\Theme;
|
||||||
|
use BookStack\Theming\ThemeEvents;
|
||||||
use DOMDocument;
|
use DOMDocument;
|
||||||
use DOMNodeList;
|
use DOMNodeList;
|
||||||
use DOMXPath;
|
use DOMXPath;
|
||||||
|
@ -53,6 +55,7 @@ class PageContent
|
||||||
$environment->addExtension(new TableExtension());
|
$environment->addExtension(new TableExtension());
|
||||||
$environment->addExtension(new TaskListExtension());
|
$environment->addExtension(new TaskListExtension());
|
||||||
$environment->addExtension(new CustomStrikeThroughExtension());
|
$environment->addExtension(new CustomStrikeThroughExtension());
|
||||||
|
$environment = Theme::dispatch(ThemeEvents::COMMONMARK_ENVIRONMENT_CONFIGURE, $environment) ?? $environment;
|
||||||
$converter = new CommonMarkConverter([], $environment);
|
$converter = new CommonMarkConverter([], $environment);
|
||||||
return $converter->convertToHtml($markdown);
|
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\ActivityService;
|
||||||
use BookStack\Actions\ViewService;
|
use BookStack\Actions\ViewService;
|
||||||
use BookStack\Auth\Permissions\PermissionService;
|
use BookStack\Auth\Permissions\PermissionService;
|
||||||
|
use BookStack\Theming\ThemeService;
|
||||||
use BookStack\Uploads\ImageService;
|
use BookStack\Uploads\ImageService;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
|
@ -42,5 +43,9 @@ class CustomFacadeProvider extends ServiceProvider
|
||||||
$this->app->singleton('permissions', function () {
|
$this->app->singleton('permissions', function () {
|
||||||
return $this->app->make(PermissionService::class);
|
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