mirror of
https://github.com/flarum/framework.git
synced 2025-02-27 03:49:56 +08:00
feat: add Less custom function extender, is-extension-enabled
function (#3190)
Co-authored-by: luceos <luceos@users.noreply.github.com> Co-authored-by: Sami Mazouz <sychocouldy@gmail.com>
This commit is contained in:
parent
eb7382b672
commit
fbfc80f979
@ -12,11 +12,13 @@ namespace Flarum\Extend;
|
|||||||
use Flarum\Extension\Extension;
|
use Flarum\Extension\Extension;
|
||||||
use Flarum\Frontend\Assets;
|
use Flarum\Frontend\Assets;
|
||||||
use Illuminate\Contracts\Container\Container;
|
use Illuminate\Contracts\Container\Container;
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
class Theme implements ExtenderInterface
|
class Theme implements ExtenderInterface
|
||||||
{
|
{
|
||||||
private $lessImportOverrides = [];
|
private $lessImportOverrides = [];
|
||||||
private $fileSourceOverrides = [];
|
private $fileSourceOverrides = [];
|
||||||
|
private $customFunctions = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This can be used to override LESS files that are imported within the code.
|
* This can be used to override LESS files that are imported within the code.
|
||||||
@ -52,8 +54,58 @@ class Theme implements ExtenderInterface
|
|||||||
return $this;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
public function extend(Container $container, Extension $extension = null)
|
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.assets.factory', function (callable $factory) {
|
$container->extend('flarum.assets.factory', function (callable $factory) {
|
||||||
return function (...$args) use ($factory) {
|
return function (...$args) use ($factory) {
|
||||||
/** @var Assets $assets */
|
/** @var Assets $assets */
|
||||||
|
@ -62,12 +62,18 @@ class Assets
|
|||||||
*/
|
*/
|
||||||
protected $fileSourceOverrides = [];
|
protected $fileSourceOverrides = [];
|
||||||
|
|
||||||
public function __construct(string $name, Filesystem $assetsDir, string $cacheDir = null, array $lessImportDirs = null)
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $customFunctions = [];
|
||||||
|
|
||||||
|
public function __construct(string $name, Filesystem $assetsDir, string $cacheDir = null, array $lessImportDirs = null, array $customFunctions = [])
|
||||||
{
|
{
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
$this->assetsDir = $assetsDir;
|
$this->assetsDir = $assetsDir;
|
||||||
$this->cacheDir = $cacheDir;
|
$this->cacheDir = $cacheDir;
|
||||||
$this->lessImportDirs = $lessImportDirs;
|
$this->lessImportDirs = $lessImportDirs;
|
||||||
|
$this->customFunctions = $customFunctions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function js($sources)
|
public function js($sources)
|
||||||
@ -173,6 +179,8 @@ class Assets
|
|||||||
$compiler->setFileSourceOverrides($this->fileSourceOverrides);
|
$compiler->setFileSourceOverrides($this->fileSourceOverrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$compiler->setCustomFunctions($this->customFunctions);
|
||||||
|
|
||||||
return $compiler;
|
return $compiler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,11 @@ class LessCompiler extends RevisionCompiler
|
|||||||
*/
|
*/
|
||||||
protected $importDirs = [];
|
protected $importDirs = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $customFunctions = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Collection
|
* @var Collection
|
||||||
*/
|
*/
|
||||||
@ -69,6 +74,11 @@ class LessCompiler extends RevisionCompiler
|
|||||||
$this->fileSourceOverrides = new Collection($fileSourceOverrides);
|
$this->fileSourceOverrides = new Collection($fileSourceOverrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setCustomFunctions(array $customFunctions)
|
||||||
|
{
|
||||||
|
$this->customFunctions = $customFunctions;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws \Less_Exception_Parser
|
* @throws \Less_Exception_Parser
|
||||||
*/
|
*/
|
||||||
@ -99,6 +109,10 @@ class LessCompiler extends RevisionCompiler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($this->customFunctions as $name => $callback) {
|
||||||
|
$parser->registerFunction($name, $callback);
|
||||||
|
}
|
||||||
|
|
||||||
return $parser->getCss();
|
return $parser->getCss();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,9 @@ class FrontendServiceProvider extends AbstractServiceProvider
|
|||||||
$assets = new Assets(
|
$assets = new Assets(
|
||||||
$name,
|
$name,
|
||||||
$container->make('filesystem')->disk('flarum-assets'),
|
$container->make('filesystem')->disk('flarum-assets'),
|
||||||
$paths->storage
|
$paths->storage,
|
||||||
|
null,
|
||||||
|
$container->make('flarum.frontend.custom_less_functions')
|
||||||
);
|
);
|
||||||
|
|
||||||
$assets->setLessImportDirs([
|
$assets->setLessImportDirs([
|
||||||
@ -110,6 +112,22 @@ class FrontendServiceProvider extends AbstractServiceProvider
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$this->container->singleton(
|
||||||
|
'flarum.frontend.custom_less_functions',
|
||||||
|
function (Container $container) {
|
||||||
|
$extensionsEnabled = json_decode($container->make(SettingsRepositoryInterface::class)->get('extensions_enabled'));
|
||||||
|
|
||||||
|
// Please note that these functions do not go through the same transformation which the Theme extender's
|
||||||
|
// `addCustomLessFunction` method does. You'll need to use the correct Less tree return type, and get
|
||||||
|
// parameter values with `$arg->value`.
|
||||||
|
return [
|
||||||
|
'is-extension-enabled' => function (\Less_Tree_Quoted $extensionId) use ($extensionsEnabled) {
|
||||||
|
return new \Less_Tree_Quoted('', in_array($extensionId->value, $extensionsEnabled) ? 'true' : 'false');
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
$this->container->singleton(TitleDriverInterface::class, function (Container $container) {
|
$this->container->singleton(TitleDriverInterface::class, function (Container $container) {
|
||||||
return $container->make(BasicTitleDriver::class);
|
return $container->make(BasicTitleDriver::class);
|
||||||
});
|
});
|
||||||
|
7
framework/core/tests/fixtures/less/custom_function.less
vendored
Normal file
7
framework/core/tests/fixtures/less/custom_function.less
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
.dummy_func_test when (is-flarum("flarum") = true) {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
.dummy_func_test2 {
|
||||||
|
--x: is-flarum("not flarum") * 10;
|
||||||
|
--y: is-gt(1, 2);
|
||||||
|
}
|
@ -104,4 +104,32 @@ class ThemeTest extends TestCase
|
|||||||
$this->assertStringContainsString('Less_Exception_Compiler', $response->getBody()->getContents());
|
$this->assertStringContainsString('Less_Exception_Compiler', $response->getBody()->getContents());
|
||||||
$this->assertEquals(500, $response->getStatusCode());
|
$this->assertEquals(500, $response->getStatusCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
public function theme_extender_can_add_custom_function()
|
||||||
|
{
|
||||||
|
$this->extend(
|
||||||
|
(new Extend\Frontend('forum'))
|
||||||
|
->css(__DIR__.'/../../fixtures/less/custom_function.less'),
|
||||||
|
(new Extend\Theme)
|
||||||
|
->addCustomLessFunction('is-flarum', function ($text) {
|
||||||
|
return strtolower($text) === 'flarum' ? 'true' : 100;
|
||||||
|
})
|
||||||
|
->addCustomLessFunction('is-gt', function ($a, $b) {
|
||||||
|
return $a > $b;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
$response = $this->send($this->request('GET', '/'));
|
||||||
|
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
|
||||||
|
$cssFilePath = $this->app()->getContainer()->make('filesystem')->disk('flarum-assets')->path('forum.css');
|
||||||
|
$contents = file_get_contents($cssFilePath);
|
||||||
|
|
||||||
|
$this->assertStringContainsString('.dummy_func_test{color:green}', $contents);
|
||||||
|
$this->assertStringContainsString('.dummy_func_test2{--x:1000;--y:false}', $contents);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user