diff --git a/application/Espo/Controllers/Formula.php b/application/Espo/Controllers/Formula.php new file mode 100644 index 0000000000..fa564f1ba4 --- /dev/null +++ b/application/Espo/Controllers/Formula.php @@ -0,0 +1,68 @@ +service = $service; + + if (!$user->isAdmin()) { + throw new ForbiddenSilent(); + } + } + + public function postActionCheckSyntax(Request $request): stdClass + { + $expression = $request->getParsedBody()->expression ?? null; + + if (!$expression || !is_string($expression)) { + throw new BadRequest("No or non-string expression."); + } + + return $this->service + ->checkSyntax($expression) + ->toStdClass(); + } +} diff --git a/application/Espo/Core/Formula/Exceptions/SyntaxError.php b/application/Espo/Core/Formula/Exceptions/SyntaxError.php index ca667435bd..22108f208d 100644 --- a/application/Espo/Core/Formula/Exceptions/SyntaxError.php +++ b/application/Espo/Core/Formula/Exceptions/SyntaxError.php @@ -31,4 +31,18 @@ namespace Espo\Core\Formula\Exceptions; class SyntaxError extends Error { + private $shortMessage = null; + + public static function create(string $message, ?string $shortMessage = null): self + { + $obj = new static($message); + $obj->shortMessage = $shortMessage; + + return $obj; + } + + public function getShortMessage(): ?string + { + return $this->shortMessage ?? $this->getMessage(); + } } diff --git a/application/Espo/Core/Formula/Parser.php b/application/Espo/Core/Formula/Parser.php index 2c993cfd5d..c4a45d7e6c 100644 --- a/application/Espo/Core/Formula/Parser.php +++ b/application/Espo/Core/Formula/Parser.php @@ -260,7 +260,10 @@ class Parser } if ($braceCounter !== 0) { - throw new SyntaxError('Incorrect round brackets in expression ' . $expression . '.'); + throw SyntaxError::create( + 'Incorrect round brackets in expression ' . $expression . '.', + 'Incorrect round brackets.' + ); } if ( diff --git a/application/Espo/Resources/i18n/en_US/Formula.json b/application/Espo/Resources/i18n/en_US/Formula.json new file mode 100644 index 0000000000..292613cdb5 --- /dev/null +++ b/application/Espo/Resources/i18n/en_US/Formula.json @@ -0,0 +1,9 @@ +{ + "labels": { + "Check Syntax": "Check Syntax" + }, + "messages": { + "checkSyntaxSuccess": "Syntax is correct.", + "checkSyntaxError": "Syntax error." + } +} diff --git a/application/Espo/Resources/metadata/scopes/Formula.json b/application/Espo/Resources/metadata/scopes/Formula.json new file mode 100644 index 0000000000..89c3030cc6 --- /dev/null +++ b/application/Espo/Resources/metadata/scopes/Formula.json @@ -0,0 +1,3 @@ +{ + "languageIsGlobal": true +} diff --git a/application/Espo/Tools/Formula/Service.php b/application/Espo/Tools/Formula/Service.php new file mode 100644 index 0000000000..58b6e1647a --- /dev/null +++ b/application/Espo/Tools/Formula/Service.php @@ -0,0 +1,57 @@ +parser = $parser; + } + + public function checkSyntax(string $expression): SyntaxCheckResult + { + try { + $this->parser->parse($expression); + + $result = SyntaxCheckResult::createSuccess(); + } + catch (SyntaxError $e) { + return SyntaxCheckResult::createError($e); + } + + return $result; + } +} diff --git a/application/Espo/Tools/Formula/SyntaxCheckResult.php b/application/Espo/Tools/Formula/SyntaxCheckResult.php new file mode 100644 index 0000000000..538a4c5bd6 --- /dev/null +++ b/application/Espo/Tools/Formula/SyntaxCheckResult.php @@ -0,0 +1,83 @@ +isSuccess = $isSuccess; + } + + public static function createSuccess(): self + { + return new self(true); + } + + public static function createError(SyntaxError $exception): self + { + $obj = new self(false); + + $obj->message = $exception->getShortMessage(); + + return $obj; + } + + public function isSuccess(): bool + { + return $this->isSuccess; + } + + public function getMessage(): ?string + { + return $this->message; + } + + public function toStdClass(): stdClass + { + $data = (object) []; + + $data->isSuccess = $this->isSuccess(); + + if (!$this->isSuccess) { + $data->message = $this->message; + } + + return $data; + } +} diff --git a/client/res/templates/fields/formula/edit.tpl b/client/res/templates/fields/formula/edit.tpl index 56a645fb6c..beac485641 100644 --- a/client/res/templates/fields/formula/edit.tpl +++ b/client/res/templates/fields/formula/edit.tpl @@ -1,22 +1,35 @@ -