/
Theme.php
161 lines (139 loc) · 5.7 KB
/
Theme.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Extend;
use Flarum\Extension\Extension;
use Flarum\Frontend\Assets;
use Illuminate\Contracts\Container\Container;
use RuntimeException;
class Theme implements ExtenderInterface
{
private $lessImportOverrides = [];
private $fileSourceOverrides = [];
private $customFunctions = [];
private $lessVariables = [];
/**
* This can be used to override LESS files that are imported within the code.
* For example, core's `forum.less` file imports a `forum/DiscussionListItem.less` file.
* The contents of this file can be overriden with this method.
*
* @param string $file : Relative path of the file to override, for example: `forum/Hero.less`
* @param string $newFilePath : Absolute path of the new file.
* @param string|null $extensionId : If overriding an extension file, specify its ID, for example: `flarum-tags`.
* @return self
*/
public function overrideLessImport(string $file, string $newFilePath, string $extensionId = null): self
{
$this->lessImportOverrides[] = compact('file', 'newFilePath', 'extensionId');
return $this;
}
/**
* This method allows overriding LESS file sources.
* For example `forum.less`, `admin.less`, `mixins.less` and `variables.less` are file sources,
* and can therefore be overriden using this method.
*
* @param string $file : Name of the file to override, for example: `admin.less`
* @param string $newFilePath : Absolute path of the new file.
* @param string|null $extensionId : If overriding an extension file, specify its ID, for example: `flarum-tags`.
* @return self
*/
public function overrideFileSource(string $file, string $newFilePath, string $extensionId = null): self
{
$this->fileSourceOverrides[] = compact('file', 'newFilePath', 'extensionId');
return $this;
}
/**
* This method allows you to add custom Less functions.
*
* All custom Less functions may only return numbers, strings or booleans.
*
* **Example usage:**
* ```php
* (new Extend\Theme)
* ->addCustomLessFunction('is-flarum', function (mixed $text) {
* return strtolower($text) === 'flarum'
* }),
* ```
*
* @see https://leafo.net/lessphp/docs/#custom_functions
*
* @param string $functionName Name of the function identifier.
* @param callable $callable The PHP function to run when the Less function is called.
* @return self
*/
public function addCustomLessFunction(string $functionName, callable $callable): self
{
$this->customFunctions[$functionName] = function (...$args) use ($callable, $functionName) {
$argVals = array_map(function ($arg) {
return $arg->value;
}, $args);
$return = $callable(...$argVals);
if (is_bool($return)) {
return new \Less_Tree_Quoted('', $return ? 'true' : 'false');
}
if (is_string($return)) {
return new \Less_Tree_Quoted('', $return);
}
if (is_numeric($return)) {
return new \Less_Tree_Dimension($return);
}
throw new RuntimeException('Custom Less function `'.$functionName.'` must only return a string, number or boolean.');
};
return $this;
}
/**
* Defines a new Less variable to be accessible in all Less files.
*
* If you want to expose a setting from your database to Less, you should use
* the `registerLessConfigVar` extender from `Extend\Settings` instead.
*
* Please note the value returned from the callable will be inserted directly
* into the Less source. If it is unsafe in some way (e.g., contains a
* semi-colon), this will result in potential security issues with your
* stylesheet.
*
* Likewise, if you need your variable to be a string, you should surround it
* with quotes yourself.
*
* ```php
* (new Extend\Theme())
* ->addCustomLessVariable('my-extension__asset_path', function () {
* $url = resolve(UrlGenerator::class);
* $assetUrl = $url->to('forum')->base().'/assets/extensions/my-extension/my-asset.jpg';
* return "\"$assetUrl\"";
* })
* ```
*
* @param string $variableName Name of the variable identifier.
* @param callable $value The PHP function to run, which returns the value for the variable.
*
* @return self
*/
public function addCustomLessVariable(string $variableName, callable $value): self
{
$this->lessVariables[$variableName] = $value;
return $this;
}
public function extend(Container $container, Extension $extension = null)
{
$container->extend('flarum.frontend.custom_less_functions', function (array $customFunctions) {
return array_merge($customFunctions, $this->customFunctions);
});
$container->extend('flarum.less.custom_variables', function (array $lessVariables) {
return array_merge($this->lessVariables, $lessVariables);
});
$container->extend('flarum.assets.factory', function (callable $factory) {
return function (...$args) use ($factory) {
/** @var Assets $assets */
$assets = $factory(...$args);
$assets->addLessImportOverrides($this->lessImportOverrides);
$assets->addFileSourceOverrides($this->fileSourceOverrides);
return $assets;
};
});
}
}