From b3649cd4d07dbb612776a0d3d0d4c18d04eea2b8 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 16 Mar 2024 07:03:50 +0100 Subject: [PATCH] Add migration routine for https://github.com/firefly-iii/firefly-iii/pull/8650 --- .../Commands/Upgrade/MigrateRuleActions.php | 187 ++++++++++++++++++ .../Commands/Upgrade/UpgradeDatabase.php | 1 + .../Commands/Upgrade/UpgradeSkeleton.php.stub | 4 +- app/Models/RuleAction.php | 4 + .../Actions/SetDescription.php | 3 + 5 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 app/Console/Commands/Upgrade/MigrateRuleActions.php diff --git a/app/Console/Commands/Upgrade/MigrateRuleActions.php b/app/Console/Commands/Upgrade/MigrateRuleActions.php new file mode 100644 index 0000000000..9fd065f8e1 --- /dev/null +++ b/app/Console/Commands/Upgrade/MigrateRuleActions.php @@ -0,0 +1,187 @@ +isExecuted() && true !== $this->option('force')) { + $this->friendlyInfo('This command has already been executed.'); + + return 0; + } + if (false === config('firefly.feature_flags.expression_engine')) { + $this->friendlyInfo('Expression engine is not enabled. Nothing to do.'); + + return 0; + } + $this->replaceEqualSign(); + $this->replaceObsoleteActions(); + + return 0; + } + + private function isExecuted(): bool + { + $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); + if (null !== $configVar) { + return (bool)$configVar->data; + } + + return false; + } + + private function markAsExecuted(): void + { + app('fireflyconfig')->set(self::CONFIG_NAME, true); + } + + private function replaceEqualSign(): void + { + $count = 0; + $actions = RuleAction::get(); + + /** @var RuleAction $action */ + foreach ($actions as $action) { + if (str_starts_with($action->action_value, '=')) { + $action->action_value = sprintf('%s%s', '\=', substr($action->action_value, 1)); + $action->save(); + ++$count; + } + } + if ($count > 0) { + $this->friendlyInfo(sprintf('Upgrading %d rule action(s) for the new expression engine.', $count)); + } + if (0 === $count) { + $this->friendlyInfo('All rule actions are up to date.'); + } + } + + private function replaceObsoleteActions(): void + { + $obsolete = [ + 'append_description', + 'prepend_description', + 'append_notes', + 'prepend_notes', + 'append_descr_to_notes', + 'append_notes_to_descr', + 'move_descr_to_notes', + 'move_notes_to_descr', + ]; + $actions = RuleAction::whereIn('action_type', $obsolete)->get(); + + /** @var RuleAction $action */ + foreach ($actions as $action) { + $oldType = $action->action_type; + + switch ($action->action_type) { + default: + $this->friendlyError(sprintf('Cannot deal with action type "%s", skip it.', $action->action_type)); + + break; + + case 'append_description': + $action->action_type = 'set_description'; + $action->action_value = sprintf('=description~"%s"', str_replace('"', '\"', $action->action_value)); + $action->save(); + $this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type)); + + break; + + case 'prepend_description': + $action->action_type = 'set_description'; + $action->action_value = sprintf('="%s"~description', str_replace('"', '\"', $action->action_value)); + $action->save(); + $this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type)); + + break; + + case 'append_notes': + $action->action_type = 'set_notes'; + $action->action_value = sprintf('=notes~"%s"', str_replace('"', '\"', $action->action_value)); + $action->save(); + $this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type)); + + break; + + case 'prepend_notes': + $action->action_type = 'set_notes'; + $action->action_value = sprintf('="%s"~notes', str_replace('"', '\"', $action->action_value)); + $action->save(); + $this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type)); + + break; + + case 'append_descr_to_notes': + $action->action_type = 'set_notes'; + $action->action_value = '=notes~" "~description'; + $action->save(); + $this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type)); + + break; + + case 'append_notes_to_descr': + $action->action_type = 'set_description'; + $action->action_value = '=description~" "~notes'; + $action->save(); + $this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type)); + + break; + + case 'move_descr_to_notes': + $action->action_type = 'set_notes'; + $action->action_value = '=description'; + $action->save(); + $this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type)); + + break; + + case 'move_notes_to_descr': + $action->action_type = 'set_description'; + $action->action_value = '=notes'; + $action->save(); + $this->friendlyInfo(sprintf('Upgraded action #%d from "%s" to "%s".', $action->id, $oldType, $action->action_type)); + + break; + } + } + } +} diff --git a/app/Console/Commands/Upgrade/UpgradeDatabase.php b/app/Console/Commands/Upgrade/UpgradeDatabase.php index bf701b585b..dae08d5f1a 100644 --- a/app/Console/Commands/Upgrade/UpgradeDatabase.php +++ b/app/Console/Commands/Upgrade/UpgradeDatabase.php @@ -63,6 +63,7 @@ class UpgradeDatabase extends Command 'firefly-iii:upgrade-liabilities', 'firefly-iii:liabilities-600', 'firefly-iii:budget-limit-periods', + 'firefly-iii:migrate-rule-actions', 'firefly-iii:restore-oauth-keys', // also just in case, some integrity commands: 'firefly-iii:create-group-memberships', diff --git a/app/Console/Commands/Upgrade/UpgradeSkeleton.php.stub b/app/Console/Commands/Upgrade/UpgradeSkeleton.php.stub index 437c42e220..d2f5b627c0 100644 --- a/app/Console/Commands/Upgrade/UpgradeSkeleton.php.stub +++ b/app/Console/Commands/Upgrade/UpgradeSkeleton.php.stub @@ -26,11 +26,11 @@ class UpgradeSkeleton extends Command { $start = microtime(true); if ($this->isExecuted() && true !== $this->option('force')) { - $this->info('FRIENDLY This command has already been executed.'); + $this->friendlyInfo('This command has already been executed.'); return 0; } - $this->warn('Congrats, you found the skeleton command. Boo!'); + $this->friendlyWarning('Congrats, you found the skeleton command. Boo!'); //$this->markAsExecuted(); diff --git a/app/Models/RuleAction.php b/app/Models/RuleAction.php index 1c1a96e3c3..37ef4f1489 100644 --- a/app/Models/RuleAction.php +++ b/app/Models/RuleAction.php @@ -85,6 +85,10 @@ class RuleAction extends Model return (string)$this->action_value; } + if (true === config('firefly.feature_flags.expression_engine') && str_starts_with($this->action_value, '\=')) { + // return literal string. + return substr($this->action_value, 1); + } $expr = new ActionExpression($this->action_value); try { diff --git a/app/TransactionRules/Actions/SetDescription.php b/app/TransactionRules/Actions/SetDescription.php index a1886ce24f..0697894a21 100644 --- a/app/TransactionRules/Actions/SetDescription.php +++ b/app/TransactionRules/Actions/SetDescription.php @@ -53,6 +53,9 @@ class SetDescription implements ActionInterface $before = $object->description; $after = $this->action->getValue($journal); + // replace newlines. + $after = str_replace(["\r", "\n", "\t", "\036", "\025"], '', $after); + \DB::table('transaction_journals') ->where('id', '=', $journal['transaction_journal_id']) ->update(['description' => $after])