fix: custom styles from 1.x can crash the app (#4159)

This commit is contained in:
Sami Mazouz 2025-01-10 16:48:24 +01:00 committed by GitHub
parent a7d584f8e1
commit 36d0795607
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 63 additions and 9 deletions

View File

@ -18,7 +18,7 @@ trim_trailing_whitespace = false
[*.{php,xml,json}] [*.{php,xml,json}]
indent_size = 4 indent_size = 4
[{tsconfig.json,prettierrc.json}] [{tsconfig.json,prettierrc.json,package.json}]
indent_size = 2 indent_size = 2
[*.neon] [*.neon]

View File

@ -1,7 +1,19 @@
import app from '../../admin/app'; import app from '../../admin/app';
import SettingsModal from './SettingsModal'; import SettingsModal, { type ISettingsModalAttrs } from './SettingsModal';
import Mithril from 'mithril';
export default class EditCustomCssModal extends SettingsModal { export default class EditCustomCssModal extends SettingsModal {
oninit(vnode: Mithril.Vnode<ISettingsModalAttrs, this>) {
super.oninit(vnode);
if (this.setting('custom_less_error')()) {
this.alertAttrs = {
type: 'error',
content: this.setting('custom_less_error')(),
};
}
}
className() { className() {
return 'EditCustomCssModal TextareaCodeModal Modal--large'; return 'EditCustomCssModal TextareaCodeModal Modal--large';
} }

View File

@ -133,7 +133,7 @@ class ForumServiceProvider extends AbstractServiceProvider
$sources->addFile(__DIR__.'/../../less/forum.less'); $sources->addFile(__DIR__.'/../../less/forum.less');
$sources->addString(function () use ($container) { $sources->addString(function () use ($container) {
return $container->make(SettingsRepositoryInterface::class)->get('custom_less', ''); return $container->make(SettingsRepositoryInterface::class)->get('custom_less', '');
}); }, 'custom_less');
}); });
$container->make(AddTranslations::class)->forFrontend('forum')->to($assets); $container->make(AddTranslations::class)->forFrontend('forum')->to($assets);
@ -195,7 +195,8 @@ class ForumServiceProvider extends AbstractServiceProvider
$container->make('flarum.assets.forum'), $container->make('flarum.assets.forum'),
$container->make('flarum.locales'), $container->make('flarum.locales'),
$container, $container,
$container->make('flarum.less.config') $container->make(SettingsRepositoryInterface::class),
$container->make('flarum.less.config'),
); );
$validator->whenSettingsSaved($event); $validator->whenSettingsSaved($event);
} }
@ -208,7 +209,8 @@ class ForumServiceProvider extends AbstractServiceProvider
$container->make('flarum.assets.forum'), $container->make('flarum.assets.forum'),
$container->make('flarum.locales'), $container->make('flarum.locales'),
$container, $container,
$container->make('flarum.less.config') $container->make(SettingsRepositoryInterface::class),
$container->make('flarum.less.config'),
); );
$validator->whenSettingsSaving($event); $validator->whenSettingsSaving($event);
} }

View File

@ -32,7 +32,8 @@ class ValidateCustomLess
protected Assets $assets, protected Assets $assets,
protected LocaleManager $locales, protected LocaleManager $locales,
protected Container $container, protected Container $container,
protected array $customLessSettings = [] protected SettingsRepositoryInterface $settings,
protected array $customLessSettings = [],
) { ) {
} }
@ -72,6 +73,8 @@ class ValidateCustomLess
$adapter = new InMemoryFilesystemAdapter(); $adapter = new InMemoryFilesystemAdapter();
$this->assets->setAssetsDir(new FilesystemAdapter(new Filesystem($adapter), $adapter)); $this->assets->setAssetsDir(new FilesystemAdapter(new Filesystem($adapter), $adapter));
$this->settings->delete('custom_less_error');
try { try {
$this->assets->makeCss()->commit(); $this->assets->makeCss()->commit();
@ -82,6 +85,10 @@ class ValidateCustomLess
throw new ValidationException(['custom_less' => $e->getMessage()]); throw new ValidationException(['custom_less' => $e->getMessage()]);
} }
if (! empty($this->settings->get('custom_less_error'))) {
throw new ValidationException(['custom_less' => $this->settings->get('custom_less_error')]);
}
$this->assets->setAssetsDir($assetsDir); $this->assets->setAssetsDir($assetsDir);
$this->container->instance(SettingsRepositoryInterface::class, $settings); $this->container->instance(SettingsRepositoryInterface::class, $settings);
} }

View File

@ -12,6 +12,7 @@ namespace Flarum\Frontend\Compiler;
use Flarum\Frontend\Compiler\Source\FileSource; use Flarum\Frontend\Compiler\Source\FileSource;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Less_Exception_Compiler;
use Less_FileManager; use Less_FileManager;
use Less_Parser; use Less_Parser;
use Less_Tree_Import; use Less_Tree_Import;
@ -71,6 +72,10 @@ class LessCompiler extends RevisionCompiler
return ''; return '';
} }
if (! empty($this->settings->get('custom_less_error'))) {
unset($sources['custom_less']);
}
ini_set('xdebug.max_nesting_level', '200'); ini_set('xdebug.max_nesting_level', '200');
$parser = new Less_Parser([ $parser = new Less_Parser([
@ -96,7 +101,27 @@ class LessCompiler extends RevisionCompiler
$parser->registerFunction($name, $callback); $parser->registerFunction($name, $callback);
} }
return $this->finalize($parser->getCss()); try {
$compiled = $this->finalize($parser->getCss());
if (isset($sources['custom_less'])) {
$this->settings->delete('custom_less_error');
}
return $compiled;
} catch (Less_Exception_Compiler $e) {
if (isset($sources['custom_less'])) {
unset($sources['custom_less']);
$compiled = $this->compile($sources);
$this->settings->set('custom_less_error', $e->getMessage());
return $compiled;
}
throw $e;
}
} }
protected function finalize(string $parsedCss): string protected function finalize(string $parsedCss): string

View File

@ -13,6 +13,7 @@ use Flarum\Frontend\Compiler\Concerns\HasSources;
use Flarum\Frontend\Compiler\Source\FileSource; use Flarum\Frontend\Compiler\Source\FileSource;
use Flarum\Frontend\Compiler\Source\SourceInterface; use Flarum\Frontend\Compiler\Source\SourceInterface;
use Flarum\Frontend\Compiler\Source\StringSource; use Flarum\Frontend\Compiler\Source\StringSource;
use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Contracts\Filesystem\Cloud; use Illuminate\Contracts\Filesystem\Cloud;
/** /**
@ -29,6 +30,7 @@ class RevisionCompiler implements CompilerInterface
public function __construct( public function __construct(
protected Cloud $assetsDir, protected Cloud $assetsDir,
protected string $filename, protected string $filename,
protected SettingsRepositoryInterface $settings
) { ) {
$this->versioner = new FileVersioner($assetsDir); $this->versioner = new FileVersioner($assetsDir);
} }

View File

@ -35,12 +35,18 @@ class SourceCollector
return $this; return $this;
} }
public function addString(Closure $callback): static public function addString(Closure $callback, ?string $key = null): static
{ {
$this->sources[] = $this->validateSourceType( $source = $this->validateSourceType(
new StringSource($callback) new StringSource($callback)
); );
if (! empty($key)) {
$this->sources[$key] = $source;
} else {
$this->sources[] = $source;
}
return $this; return $this;
} }