. */ declare(strict_types=1); namespace FireflyIII\TransactionRules\Expressions; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\ExpressionLanguage\SyntaxError; class ActionExpression { private static array $NAMES = array( "id", "created_at", "updated_at", "deleted_at", "user_id", "transaction_type_id", "transaction_group_id", "bill_id", "transaction_currency_id", "description", "date", "interest_date", "book_date", "process_date", "order", "tag_count", "transaction_type_type", "encrypted", "completed", "attachments", "attachments_count", "bill", "budgets", "budgets_count", "categories", "categories_count", "destJournalLinks", "dest_journal_links_count", "notes", "notes_count", "piggyBankEvents", "piggy_bank_events_count", "sourceJournalLinks", "source_journal_links_count", "tags", "tags_count", "transactionCurrency", "transactionGroup", "transactionJournalMeta", "transaction_journal_meta_count", "transactionType", "transactions", "transactions_count", "user", ); private ExpressionLanguage $expressionLanguage; private string $expr; private bool $isExpression; private ?SyntaxError $validationError; public function __construct(string $expr) { $this->expressionLanguage = app(ExpressionLanguage::class); $this->expr = $expr; $this->isExpression = self::isExpression($expr); $this->validationError = $this->validate(); } private static function isExpression(string $expr): bool { return str_starts_with($expr, "="); } private function validate(): ?SyntaxError { if (!$this->isExpression) { return null; } try { $this->lint(); return null; } catch (SyntaxError $e) { return $e; } } private function lintExpression(string $expr): void { $this->expressionLanguage->lint($expr, self::$NAMES); } private function lint(): void { if (!$this->isExpression) { return; } $this->lintExpression(substr($this->expr, 1)); } public function isValid(): bool { return $this->validationError === null; } public function getValidationError() { return $this->validationError; } private function evaluateExpression(string $expr, array $journal): string { $result = $this->expressionLanguage->evaluate($expr, $journal); return strval($result); } public function evaluate(array $journal): string { if (!$this->isExpression) { return $this->expr; } return $this->evaluateExpression(substr($this->expr, 1), $journal); } }