refactor: inject ExpressionLanguage singleton using DI

This commit is contained in:
Michael Thomas
2024-03-07 13:00:57 -05:00
parent 438f602961
commit bee219ebf7
21 changed files with 122 additions and 164 deletions

View File

@@ -26,11 +26,9 @@ namespace FireflyIII\Api\V1\Controllers\Models\Rule;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\Rule\ValidateExpressionRequest; use FireflyIII\Api\V1\Requests\Models\Rule\ValidateExpressionRequest;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface; use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
use FireflyIII\TransactionRules\Factory\ExpressionLanguageFactory;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Symfony\Component\ExpressionLanguage\SyntaxError;
/** /**
* Class ExpressionController * Class ExpressionController
@@ -70,18 +68,17 @@ class ExpressionController extends Controller
*/ */
public function validateExpression(ValidateExpressionRequest $request): JsonResponse public function validateExpression(ValidateExpressionRequest $request): JsonResponse
{ {
$expr = $request->getExpression(); $value = $request->getExpression();
$expressionLanguage = ExpressionLanguageFactory::get(); $expr = new ActionExpression($value);
$evaluator = new ActionExpressionEvaluator($expressionLanguage, $expr);
if ($evaluator->isValid()) { if ($expr->isValid()) {
return response()->json([ return response()->json([
"valid" => true, "valid" => true,
]); ]);
} else { } else {
return response()->json([ return response()->json([
"valid" => false, "valid" => false,
"error" => $evaluator->getValidationError()->getMessage() "error" => $expr->getValidationError()->getMessage()
]); ]);
} }
} }

View File

@@ -19,6 +19,7 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
declare(strict_types=1); declare(strict_types=1);
namespace FireflyIII\Providers; namespace FireflyIII\Providers;
@@ -69,9 +70,11 @@ use FireflyIII\Support\Preferences;
use FireflyIII\Support\Steam; use FireflyIII\Support\Steam;
use FireflyIII\TransactionRules\Engine\RuleEngineInterface; use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
use FireflyIII\TransactionRules\Engine\SearchRuleEngine; use FireflyIII\TransactionRules\Engine\SearchRuleEngine;
use FireflyIII\TransactionRules\Expressions\ActionExpressionLanguageProvider;
use FireflyIII\Validation\FireflyValidator; use FireflyIII\Validation\FireflyValidator;
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
/** /**
* Class FireflyServiceProvider. * Class FireflyServiceProvider.
@@ -200,6 +203,16 @@ class FireflyServiceProvider extends ServiceProvider
} }
); );
// rule expression language
$this->app->singleton(
ExpressionLanguage::class,
static function () {
$expressionLanguage = new ExpressionLanguage();
$expressionLanguage->registerProvider(new ActionExpressionLanguageProvider());
return $expressionLanguage;
}
);
$this->app->bind( $this->app->bind(
RuleEngineInterface::class, RuleEngineInterface::class,
static function (Application $app) { static function (Application $app) {

View File

@@ -29,7 +29,7 @@ use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Factory\TagFactory; use FireflyIII\Factory\TagFactory;
use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
use FireflyIII\User; use FireflyIII\User;
/** /**
@@ -38,15 +38,15 @@ use FireflyIII\User;
class AddTag implements ActionInterface class AddTag implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;
private ActionExpressionEvaluator $evaluator; private ActionExpression $expr;
/** /**
* TriggerInterface constructor. * TriggerInterface constructor.
*/ */
public function __construct(RuleAction $action, ActionExpressionEvaluator $evaluator) public function __construct(RuleAction $action, ActionExpression $expr)
{ {
$this->action = $action; $this->action = $action;
$this->evaluator = $evaluator; $this->expr = $expr;
} }
public function actOnArray(array $journal): bool public function actOnArray(array $journal): bool
@@ -58,7 +58,7 @@ class AddTag implements ActionInterface
/** @var User $user */ /** @var User $user */
$user = User::find($journal['user_id']); $user = User::find($journal['user_id']);
$factory->setUser($user); $factory->setUser($user);
$tagName = $this->evaluator->evaluate($journal); $tagName = $this->expr->evaluate($journal);
$tag = $factory->findOrCreate($tagName); $tag = $factory->findOrCreate($tagName);
if (null === $tag) { if (null === $tag) {

View File

@@ -27,7 +27,7 @@ namespace FireflyIII\TransactionRules\Actions;
use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
/** /**
* Class AppendDescription. * Class AppendDescription.
@@ -35,20 +35,20 @@ use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator;
class AppendDescription implements ActionInterface class AppendDescription implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;
private ActionExpressionEvaluator $evaluator; private ActionExpression $expr;
/** /**
* TriggerInterface constructor. * TriggerInterface constructor.
*/ */
public function __construct(RuleAction $action, ActionExpressionEvaluator $evaluator) public function __construct(RuleAction $action, ActionExpression $expr)
{ {
$this->action = $action; $this->action = $action;
$this->evaluator = $evaluator; $this->expr = $expr;
} }
public function actOnArray(array $journal): bool public function actOnArray(array $journal): bool
{ {
$actionValue = $this->evaluator->evaluate($journal); $actionValue = $this->expr->evaluate($journal);
$description = sprintf('%s %s', $journal['description'], $actionValue); $description = sprintf('%s %s', $journal['description'], $actionValue);
\DB::table('transaction_journals')->where('id', $journal['transaction_journal_id'])->limit(1)->update(['description' => $description]); \DB::table('transaction_journals')->where('id', $journal['transaction_journal_id'])->limit(1)->update(['description' => $description]);

View File

@@ -28,7 +28,7 @@ use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\Note; use FireflyIII\Models\Note;
use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
/** /**
* Class AppendNotes. * Class AppendNotes.
@@ -36,20 +36,20 @@ use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator;
class AppendNotes implements ActionInterface class AppendNotes implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;
private ActionExpressionEvaluator $evaluator; private ActionExpression $expr;
/** /**
* TriggerInterface constructor. * TriggerInterface constructor.
*/ */
public function __construct(RuleAction $action, ActionExpressionEvaluator $evaluator) public function __construct(RuleAction $action, ActionExpression $expr)
{ {
$this->action = $action; $this->action = $action;
$this->evaluator = $evaluator; $this->expr = $expr;
} }
public function actOnArray(array $journal): bool public function actOnArray(array $journal): bool
{ {
$actionValue = $this->evaluator->evaluate($journal); $actionValue = $this->expr->evaluate($journal);
$dbNote = Note::where('noteable_id', (int)$journal['transaction_journal_id']) $dbNote = Note::where('noteable_id', (int)$journal['transaction_journal_id'])
->where('noteable_type', TransactionJournal::class) ->where('noteable_type', TransactionJournal::class)
->first(['notes.*']); ->first(['notes.*']);

View File

@@ -35,7 +35,7 @@ use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
/** /**
* Class ConvertToDeposit * Class ConvertToDeposit
@@ -43,20 +43,20 @@ use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator;
class ConvertToDeposit implements ActionInterface class ConvertToDeposit implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;
private ActionExpressionEvaluator $evaluator; private ActionExpression $expr;
/** /**
* TriggerInterface constructor. * TriggerInterface constructor.
*/ */
public function __construct(RuleAction $action, ActionExpressionEvaluator $evaluator) public function __construct(RuleAction $action, ActionExpression $expr)
{ {
$this->action = $action; $this->action = $action;
$this->evaluator = $evaluator; $this->expr = $expr;
} }
public function actOnArray(array $journal): bool public function actOnArray(array $journal): bool
{ {
$actionValue = $this->evaluator->evaluate($journal); $actionValue = $this->expr->evaluate($journal);
// make object from array (so the data is fresh). // make object from array (so the data is fresh).
/** @var null|TransactionJournal $object */ /** @var null|TransactionJournal $object */

View File

@@ -34,7 +34,7 @@ use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
/** /**
* Class ConvertToTransfer * Class ConvertToTransfer
@@ -42,15 +42,15 @@ use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator;
class ConvertToTransfer implements ActionInterface class ConvertToTransfer implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;
private ActionExpressionEvaluator $evaluator; private ActionExpression $expr;
/** /**
* TriggerInterface constructor. * TriggerInterface constructor.
*/ */
public function __construct(RuleAction $action, ActionExpressionEvaluator $evaluator) public function __construct(RuleAction $action, ActionExpression $expr)
{ {
$this->action = $action; $this->action = $action;
$this->evaluator = $evaluator; $this->expr = $expr;
} }
/** /**
@@ -59,7 +59,7 @@ class ConvertToTransfer implements ActionInterface
*/ */
public function actOnArray(array $journal): bool public function actOnArray(array $journal): bool
{ {
$actionValue = $this->evaluator->evaluate($journal); $actionValue = $this->expr->evaluate($journal);
// make object from array (so the data is fresh). // make object from array (so the data is fresh).
/** @var null|TransactionJournal $object */ /** @var null|TransactionJournal $object */

View File

@@ -35,7 +35,7 @@ use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
/** /**
* Class ConvertToWithdrawal * Class ConvertToWithdrawal
@@ -43,20 +43,20 @@ use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator;
class ConvertToWithdrawal implements ActionInterface class ConvertToWithdrawal implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;
private ActionExpressionEvaluator $evaluator; private ActionExpression $expr;
/** /**
* TriggerInterface constructor. * TriggerInterface constructor.
*/ */
public function __construct(RuleAction $action, ActionExpressionEvaluator $evaluator) public function __construct(RuleAction $action, ActionExpression $expr)
{ {
$this->action = $action; $this->action = $action;
$this->evaluator = $evaluator; $this->expr = $expr;
} }
public function actOnArray(array $journal): bool public function actOnArray(array $journal): bool
{ {
$actionValue = $this->evaluator->evaluate($journal); $actionValue = $this->expr->evaluate($journal);
// make object from array (so the data is fresh). // make object from array (so the data is fresh).
/** @var null|TransactionJournal $object */ /** @var null|TransactionJournal $object */

View File

@@ -30,7 +30,7 @@ use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
use FireflyIII\User; use FireflyIII\User;
/** /**
@@ -39,15 +39,15 @@ use FireflyIII\User;
class LinkToBill implements ActionInterface class LinkToBill implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;
private ActionExpressionEvaluator $evaluator; private ActionExpression $expr;
/** /**
* TriggerInterface constructor. * TriggerInterface constructor.
*/ */
public function __construct(RuleAction $action, ActionExpressionEvaluator $evaluator) public function __construct(RuleAction $action, ActionExpression $expr)
{ {
$this->action = $action; $this->action = $action;
$this->evaluator = $evaluator; $this->expr = $expr;
} }
public function actOnArray(array $journal): bool public function actOnArray(array $journal): bool
@@ -58,7 +58,7 @@ class LinkToBill implements ActionInterface
/** @var BillRepositoryInterface $repository */ /** @var BillRepositoryInterface $repository */
$repository = app(BillRepositoryInterface::class); $repository = app(BillRepositoryInterface::class);
$repository->setUser($user); $repository->setUser($user);
$billName = $this->evaluator->evaluate($journal); $billName = $this->expr->evaluate($journal);
$bill = $repository->findByName($billName); $bill = $repository->findByName($billName);
if (null !== $bill && TransactionType::WITHDRAWAL === $journal['transaction_type_type']) { if (null !== $bill && TransactionType::WITHDRAWAL === $journal['transaction_type_type']) {

View File

@@ -27,7 +27,7 @@ namespace FireflyIII\TransactionRules\Actions;
use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
/** /**
* Class PrependDescription. * Class PrependDescription.
@@ -35,20 +35,20 @@ use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator;
class PrependDescription implements ActionInterface class PrependDescription implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;
private ActionExpressionEvaluator $evaluator; private ActionExpression $expr;
/** /**
* TriggerInterface constructor. * TriggerInterface constructor.
*/ */
public function __construct(RuleAction $action, ActionExpressionEvaluator $evaluator) public function __construct(RuleAction $action, ActionExpression $expr)
{ {
$this->action = $action; $this->action = $action;
$this->evaluator = $evaluator; $this->expr = $expr;
} }
public function actOnArray(array $journal): bool public function actOnArray(array $journal): bool
{ {
$actionValue = $this->evaluator->evaluate($journal); $actionValue = $this->expr->evaluate($journal);
$before = $journal['description']; $before = $journal['description'];
$after = sprintf('%s%s', $actionValue, $journal['description']); $after = sprintf('%s%s', $actionValue, $journal['description']);

View File

@@ -28,7 +28,7 @@ use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\Note; use FireflyIII\Models\Note;
use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
/** /**
* Class PrependNotes. * Class PrependNotes.
@@ -36,20 +36,20 @@ use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator;
class PrependNotes implements ActionInterface class PrependNotes implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;
private ActionExpressionEvaluator $evaluator; private ActionExpression $expr;
/** /**
* TriggerInterface constructor. * TriggerInterface constructor.
*/ */
public function __construct(RuleAction $action, ActionExpressionEvaluator $evaluator) public function __construct(RuleAction $action, ActionExpression $expr)
{ {
$this->action = $action; $this->action = $action;
$this->evaluator = $evaluator; $this->expr = $expr;
} }
public function actOnArray(array $journal): bool public function actOnArray(array $journal): bool
{ {
$actionValue = $this->evaluator->evaluate($journal); $actionValue = $this->expr->evaluate($journal);
$dbNote = Note::where('noteable_id', (int)$journal['transaction_journal_id']) $dbNote = Note::where('noteable_id', (int)$journal['transaction_journal_id'])
->where('noteable_type', TransactionJournal::class) ->where('noteable_type', TransactionJournal::class)
->first(['notes.*']); ->first(['notes.*']);

View File

@@ -28,7 +28,7 @@ use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
use FireflyIII\User; use FireflyIII\User;
/** /**
@@ -37,21 +37,21 @@ use FireflyIII\User;
class RemoveTag implements ActionInterface class RemoveTag implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;
private ActionExpressionEvaluator $evaluator; private ActionExpression $expr;
/** /**
* TriggerInterface constructor. * TriggerInterface constructor.
*/ */
public function __construct(RuleAction $action, ActionExpressionEvaluator $evaluator) public function __construct(RuleAction $action, ActionExpression $expr)
{ {
$this->action = $action; $this->action = $action;
$this->evaluator = $evaluator; $this->expr = $expr;
} }
public function actOnArray(array $journal): bool public function actOnArray(array $journal): bool
{ {
// if tag does not exist, no need to continue: // if tag does not exist, no need to continue:
$name = $this->evaluator->evaluate($journal); $name = $this->expr->evaluate($journal);
/** @var User $user */ /** @var User $user */
$user = User::find($journal['user_id']); $user = User::find($journal['user_id']);

View File

@@ -29,7 +29,7 @@ use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
use FireflyIII\User; use FireflyIII\User;
/** /**
@@ -38,22 +38,22 @@ use FireflyIII\User;
class SetBudget implements ActionInterface class SetBudget implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;
private ActionExpressionEvaluator $evaluator; private ActionExpression $expr;
/** /**
* TriggerInterface constructor. * TriggerInterface constructor.
*/ */
public function __construct(RuleAction $action, ActionExpressionEvaluator $evaluator) public function __construct(RuleAction $action, ActionExpression $expr)
{ {
$this->action = $action; $this->action = $action;
$this->evaluator = $evaluator; $this->expr = $expr;
} }
public function actOnArray(array $journal): bool public function actOnArray(array $journal): bool
{ {
/** @var User $user */ /** @var User $user */
$user = User::find($journal['user_id']); $user = User::find($journal['user_id']);
$search = $this->evaluator->evaluate($journal); $search = $this->expr->evaluate($journal);
$budget = $user->budgets()->where('name', $search)->first(); $budget = $user->budgets()->where('name', $search)->first();
if (null === $budget) { if (null === $budget) {

View File

@@ -29,7 +29,7 @@ use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Factory\CategoryFactory; use FireflyIII\Factory\CategoryFactory;
use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
use FireflyIII\User; use FireflyIII\User;
/** /**
@@ -38,22 +38,22 @@ use FireflyIII\User;
class SetCategory implements ActionInterface class SetCategory implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;
private ActionExpressionEvaluator $evaluator; private ActionExpression $expr;
/** /**
* TriggerInterface constructor. * TriggerInterface constructor.
*/ */
public function __construct(RuleAction $action, ActionExpressionEvaluator $evaluator) public function __construct(RuleAction $action, ActionExpression $expr)
{ {
$this->action = $action; $this->action = $action;
$this->evaluator = $evaluator; $this->expr = $expr;
} }
public function actOnArray(array $journal): bool public function actOnArray(array $journal): bool
{ {
/** @var null|User $user */ /** @var null|User $user */
$user = User::find($journal['user_id']); $user = User::find($journal['user_id']);
$search = $this->evaluator->evaluate($journal); $search = $this->expr->evaluate($journal);
if (null === $user) { if (null === $user) {
app('log')->error(sprintf('Journal has no valid user ID so action SetCategory("%s") cannot be applied', $search), $journal); app('log')->error(sprintf('Journal has no valid user ID so action SetCategory("%s") cannot be applied', $search), $journal);
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_such_journal'))); event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_such_journal')));

View File

@@ -27,7 +27,7 @@ namespace FireflyIII\TransactionRules\Actions;
use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
/** /**
* Class SetDescription. * Class SetDescription.
@@ -35,15 +35,15 @@ use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator;
class SetDescription implements ActionInterface class SetDescription implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;
private ActionExpressionEvaluator $evaluator; private ActionExpression $expr;
/** /**
* TriggerInterface constructor. * TriggerInterface constructor.
*/ */
public function __construct(RuleAction $action, ActionExpressionEvaluator $evaluator) public function __construct(RuleAction $action, ActionExpression $expr)
{ {
$this->action = $action; $this->action = $action;
$this->evaluator = $evaluator; $this->expr = $expr;
} }
public function actOnArray(array $journal): bool public function actOnArray(array $journal): bool
@@ -51,7 +51,7 @@ class SetDescription implements ActionInterface
/** @var TransactionJournal $object */ /** @var TransactionJournal $object */
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
$before = $journal['description']; $before = $journal['description'];
$after = $this->evaluator->evaluate($journal); $after = $this->expr->evaluate($journal);
\DB::table('transaction_journals') \DB::table('transaction_journals')
->where('id', '=', $journal['transaction_journal_id']) ->where('id', '=', $journal['transaction_journal_id'])

View File

@@ -28,7 +28,7 @@ use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Models\Note; use FireflyIII\Models\Note;
use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
/** /**
* Class SetNotes. * Class SetNotes.
@@ -36,15 +36,15 @@ use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator;
class SetNotes implements ActionInterface class SetNotes implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;
private ActionExpressionEvaluator $evaluator; private ActionExpression $expr;
/** /**
* TriggerInterface constructor. * TriggerInterface constructor.
*/ */
public function __construct(RuleAction $action, ActionExpressionEvaluator $evaluator) public function __construct(RuleAction $action, ActionExpression $expr)
{ {
$this->action = $action; $this->action = $action;
$this->evaluator = $evaluator; $this->expr = $expr;
} }
public function actOnArray(array $journal): bool public function actOnArray(array $journal): bool
@@ -58,7 +58,7 @@ class SetNotes implements ActionInterface
$dbNote->text = ''; $dbNote->text = '';
} }
$oldNotes = $dbNote->text; $oldNotes = $dbNote->text;
$newNotes = $this->evaluator->evaluate($journal); $newNotes = $this->expr->evaluate($journal);
$dbNote->text = $newNotes; $dbNote->text = $newNotes;
$dbNote->save(); $dbNote->save();

View File

@@ -31,7 +31,7 @@ use FireflyIII\Models\RuleAction;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
use FireflyIII\User; use FireflyIII\User;
/** /**
@@ -40,22 +40,22 @@ use FireflyIII\User;
class UpdatePiggybank implements ActionInterface class UpdatePiggybank implements ActionInterface
{ {
private RuleAction $action; private RuleAction $action;
private ActionExpressionEvaluator $evaluator; private ActionExpression $expr;
/** /**
* TriggerInterface constructor. * TriggerInterface constructor.
*/ */
public function __construct(RuleAction $action, ActionExpressionEvaluator $evaluator) public function __construct(RuleAction $action, ActionExpression $expr)
{ {
$this->action = $action; $this->action = $action;
$this->evaluator = $evaluator; $this->expr = $expr;
} }
public function actOnArray(array $journal): bool public function actOnArray(array $journal): bool
{ {
app('log')->debug(sprintf('Triggered rule action UpdatePiggybank on journal #%d', $journal['transaction_journal_id'])); app('log')->debug(sprintf('Triggered rule action UpdatePiggybank on journal #%d', $journal['transaction_journal_id']));
$piggyBankName = $this->evaluator->evaluate($journal); $piggyBankName = $this->expr->evaluate($journal);
// refresh the transaction type. // refresh the transaction type.
/** @var User $user */ /** @var User $user */
$user = User::find($journal['user_id']); $user = User::find($journal['user_id']);

View File

@@ -1,7 +1,7 @@
<?php <?php
/** /**
* ActionExpressionEvaluator.php * ActionExpression.php
* Copyright (c) 2024 Michael Thomas * Copyright (c) 2024 Michael Thomas
* *
* This file is part of Firefly III (https://github.com/firefly-iii). * This file is part of Firefly III (https://github.com/firefly-iii).
@@ -27,7 +27,7 @@ namespace FireflyIII\TransactionRules\Expressions;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\ExpressionLanguage\SyntaxError; use Symfony\Component\ExpressionLanguage\SyntaxError;
class ActionExpressionEvaluator class ActionExpression
{ {
private static array $NAMES = array("transaction"); private static array $NAMES = array("transaction");
@@ -36,9 +36,9 @@ class ActionExpressionEvaluator
private bool $isExpression; private bool $isExpression;
private ?SyntaxError $validationError; private ?SyntaxError $validationError;
public function __construct(ExpressionLanguage $expressionLanguage, string $expr) public function __construct(string $expr)
{ {
$this->expressionLanguage = $expressionLanguage; $this->expressionLanguage = app(ExpressionLanguage::class);
$this->expr = $expr; $this->expr = $expr;
$this->isExpression = self::isExpression($expr); $this->isExpression = self::isExpression($expr);

View File

@@ -28,8 +28,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleAction;
use FireflyIII\Support\Domain; use FireflyIII\Support\Domain;
use FireflyIII\TransactionRules\Actions\ActionInterface; use FireflyIII\TransactionRules\Actions\ActionInterface;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
use FireflyIII\TransactionRules\Factory\ExpressionLanguageFactory;
/** /**
* Class ActionFactory can create actions. * Class ActionFactory can create actions.
@@ -52,10 +51,9 @@ class ActionFactory
$class = self::getActionClass($action->action_type); $class = self::getActionClass($action->action_type);
app('log')->debug(sprintf('self::getActionClass("%s") = "%s"', $action->action_type, $class)); app('log')->debug(sprintf('self::getActionClass("%s") = "%s"', $action->action_type, $class));
$expressionLanguage = ExpressionLanguageFactory::get(); $expr = new ActionExpression($action->action_value);
$expressionEvaluator = new ActionExpressionEvaluator($expressionLanguage, $action->action_value);
return new $class($action, $expressionEvaluator); // @phpstan-ignore-line return new $class($action, $expr); // @phpstan-ignore-line
} }
/** /**

View File

@@ -1,45 +0,0 @@
<?php
/**
* ExpressionLanguageFactory.php
* Copyright (c) 2024 Michael Thomas
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\TransactionRules\Factory;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use FireflyIII\TransactionRules\Expressions\ActionExpressionLanguageProvider;
class ExpressionLanguageFactory
{
protected static ExpressionLanguage $expressionLanguage;
private static function constructExpressionLanguage(): ExpressionLanguage
{
$expressionLanguage = new ExpressionLanguage();
$expressionLanguage->registerProvider(new ActionExpressionLanguageProvider());
return $expressionLanguage;
}
public static function get(): ExpressionLanguage
{
return self::$expressionLanguage ??= self::constructExpressionLanguage();
}
}

View File

@@ -35,8 +35,7 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Services\Password\Verifier; use FireflyIII\Services\Password\Verifier;
use FireflyIII\Support\ParseDateString; use FireflyIII\Support\ParseDateString;
use FireflyIII\TransactionRules\Expressions\ActionExpressionEvaluator; use FireflyIII\TransactionRules\Expressions\ActionExpression;
use FireflyIII\TransactionRules\Factory\ExpressionLanguageFactory;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Validation\Validator; use Illuminate\Validation\Validator;
use PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException; use PragmaRX\Google2FA\Exceptions\IncompatibleWithGoogleAuthenticatorException;
@@ -258,20 +257,16 @@ class FireflyValidator extends Validator
public function validateRuleActionExpression(string $attribute, string $value = null): bool public function validateRuleActionExpression(string $attribute, string $value = null): bool
{ {
$value ??= ''; $value ??= '';
$expr = new ActionExpression($value);
$el = ExpressionLanguageFactory::get(); return $expr->isValid();
$evaluator = new ActionExpressionEvaluator($el, $value);
return $evaluator->isValid();
} }
public function replaceRuleActionExpression(string $message, string $attribute): string public function replaceRuleActionExpression(string $message, string $attribute): string
{ {
$value = $this->getValue($attribute); $value = $this->getValue($attribute);
$expr = new ActionExpression($value);
$el = ExpressionLanguageFactory::get(); $err = $expr->getValidationError();
$evaluator = new ActionExpressionEvaluator($el, $value);
$err = $evaluator->getValidationError();
if ($err == null) { if ($err == null) {
return $message; return $message;