diff --git a/app/Http/Controllers/Auth/AuthController.php b/app/Http/Controllers/Auth/AuthController.php index 7bf7a47d82..93376784cd 100644 --- a/app/Http/Controllers/Auth/AuthController.php +++ b/app/Http/Controllers/Auth/AuthController.php @@ -4,6 +4,7 @@ declare(strict_types = 1); namespace FireflyIII\Http\Controllers\Auth; use Auth; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Role; use FireflyIII\User; @@ -151,7 +152,7 @@ class AuthController extends Controller return redirect($this->redirectPath()); } - abort(500, 'Not a user!'); + throw new FireflyException('The authenticated user object is invalid.'); return redirect($this->redirectPath()); diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index 78fbc0ec4f..8e11142d10 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -3,6 +3,7 @@ use Amount; use Carbon\Carbon; use Config; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Report\ReportQueryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI; use FireflyIII\Repositories\Bill\BillRepositoryInterface; @@ -247,7 +248,7 @@ class JsonController extends Controller { $pref = Preferences::get('tour', true); if (!$pref) { - abort(404); + throw new FireflyException('Cannot find preference for tour. Exit.'); } $headers = ['main-content', 'sidebar-toggle', 'account-menu', 'budget-menu', 'report-menu', 'transaction-menu', 'option-menu', 'main-content-end']; $steps = []; diff --git a/app/Http/Requests/JournalFormRequest.php b/app/Http/Requests/JournalFormRequest.php index ee9fdf0788..060a41dbb8 100644 --- a/app/Http/Requests/JournalFormRequest.php +++ b/app/Http/Requests/JournalFormRequest.php @@ -6,6 +6,7 @@ namespace FireflyIII\Http\Requests; use Auth; use Carbon\Carbon; use Exception; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\TransactionType; use Input; @@ -32,6 +33,7 @@ class JournalFormRequest extends Request public function getJournalData() { $tags = $this->get('tags') ?? ''; + return [ 'what' => $this->get('what'), 'description' => $this->get('description'), @@ -86,7 +88,7 @@ class JournalFormRequest extends Request $rules['category'] = 'between:1,255'; break; default: - abort(500, 'Cannot handle ' . $what); + throw new FireflyException('Cannot handle transaction type of type ' . e($what) . '.'); break; } diff --git a/app/Models/RuleTrigger.php b/app/Models/RuleTrigger.php index dc92048977..365e873722 100644 --- a/app/Models/RuleTrigger.php +++ b/app/Models/RuleTrigger.php @@ -10,6 +10,7 @@ declare(strict_types = 1); namespace FireflyIII\Models; +use FireflyIII\Rules\Triggers\TriggerFactory; use Illuminate\Database\Eloquent\Model; /** @@ -29,6 +30,15 @@ use Illuminate\Database\Eloquent\Model; */ class RuleTrigger extends Model { + /** + * Checks whether this trigger will match all transactions + * For example: amount > 0 or description starts with '' + */ + public function matchesAnything() + { + return TriggerFactory::getTrigger($this, new TransactionJournal)->matchesAnything(); + } + /** * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 99cf93bff8..7a90bb7386 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -7,6 +7,7 @@ use Auth; use Carbon\Carbon; use Config; use DB; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; use FireflyIII\Models\AccountMeta; use FireflyIII\Models\AccountType; @@ -482,7 +483,9 @@ class AccountRepository implements AccountRepositoryInterface $existingAccount = Account::firstOrNullEncrypted($searchData); if (!$existingAccount) { Log::error('Account create error: ' . $newAccount->getErrors()->toJson()); - abort(500); + throw new FireflyException( + 'Cannot create a new account. See also the log files. First error is: ' . e($newAccount->getErrors()->first()) . '.' + ); } $newAccount = $existingAccount; diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index 9de4c9785b..c90fcb19f0 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -6,6 +6,7 @@ namespace FireflyIII\Repositories\Journal; use Auth; use Carbon\Carbon; use DB; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\Budget; @@ -349,14 +350,14 @@ class JournalRepository implements JournalRepositoryInterface if (is_null($toAccount)) { Log::error('"to"-account is null, so we cannot continue!'); - abort(500, '"to"-account is null, so we cannot continue!'); + throw new FireflyException('"to"-account is null, so we cannot continue!'); // @codeCoverageIgnoreStart } // @codeCoverageIgnoreEnd if (is_null($fromAccount)) { Log::error('"from"-account is null, so we cannot continue!'); - abort(500, '"from"-account is null, so we cannot continue!'); + throw new FireflyException('"from"-account is null, so we cannot continue!'); // @codeCoverageIgnoreStart } diff --git a/app/Rules/Actions/ActionFactory.php b/app/Rules/Actions/ActionFactory.php new file mode 100644 index 0000000000..5c525e79af --- /dev/null +++ b/app/Rules/Actions/ActionFactory.php @@ -0,0 +1,78 @@ +action_type; + $class = self::getActionClass($actionType); + + return new $class($action, $journal); + } + + /** + * Returns the class name to be used for actions with the given name + * + * @param string $actionType + * + * @return ActionInterface|string + * @throws FireflyException + */ + public static function getActionClass(string $actionType): string + { + $actionTypes = self::getActionTypes(); + + if (!array_key_exists($actionType, $actionTypes)) { + throw new FireflyException('No such action exists ("' . e($actionType) . '").'); + } + + $class = $actionTypes[$actionType]; + if (!class_exists($class)) { + throw new FireflyException('Could not instantiate class for rule action type "' . e($actionType) . '" (' . e($class) . ').'); + } + + return $class; + } + + /** + * Returns a map with actiontypes, mapped to the class representing that type + */ + protected static function getActionTypes() + { + if (!self::$actionTypes) { + self::$actionTypes = Domain::getRuleActions(); + } + + return self::$actionTypes; + } +} diff --git a/app/Rules/Processor.php b/app/Rules/Processor.php index 1b1d78341b..645ef47e68 100644 --- a/app/Rules/Processor.php +++ b/app/Rules/Processor.php @@ -15,8 +15,9 @@ use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleTrigger; use FireflyIII\Models\TransactionJournal; use FireflyIII\Rules\Actions\ActionInterface; +use FireflyIII\Rules\Actions\ActionFactory; use FireflyIII\Rules\Triggers\TriggerInterface; -use FireflyIII\Support\Domain; +use FireflyIII\Rules\Triggers\TriggerFactory; use Log; /** @@ -30,10 +31,6 @@ class Processor protected $journal; /** @var Rule */ protected $rule; - /** @var array */ - private $actionTypes = []; - /** @var array */ - private $triggerTypes = []; /** * Processor constructor. @@ -45,8 +42,6 @@ class Processor { $this->rule = $rule; $this->journal = $journal; - $this->triggerTypes = Domain::getRuleTriggers(); - $this->actionTypes = Domain::getRuleActions(); } /** @@ -118,14 +113,8 @@ class Processor * @var RuleAction $action */ foreach ($this->rule->ruleActions()->orderBy('order', 'ASC')->get() as $action) { - $type = $action->action_type; - $class = $this->actionTypes[$type]; - Log::debug('Action #' . $action->id . ' for rule #' . $action->rule_id . ' (' . $type . ')'); - if (!class_exists($class)) { - abort(500, 'Could not instantiate class for rule action type "' . $type . '" (' . $class . ').'); - } /** @var ActionInterface $actionClass */ - $actionClass = new $class($action, $this->journal); + $actionClass = ActionFactory::getAction($action, $this->journal); $actionClass->act(); if ($action->stop_processing) { break; @@ -137,8 +126,6 @@ class Processor } /** - * Method to check whether the current transaction would be triggered - * by the given list of triggers * @return bool */ protected function triggeredBy($triggers) { @@ -147,29 +134,19 @@ class Processor /** @var RuleTrigger $trigger */ foreach ($triggers as $trigger) { $foundTriggers++; - $type = $trigger->trigger_type; - - if (!isset($this->triggerTypes[$type])) { - abort(500, 'No such trigger exists ("' . $type . '").'); - } - - $class = $this->triggerTypes[$type]; - Log::debug('Trigger #' . $trigger->id . ' for rule #' . $trigger->rule_id . ' (' . $type . ')'); - if (!class_exists($class)) { - abort(500, 'Could not instantiate class for rule trigger type "' . $type . '" (' . $class . ').'); - } + /** @var TriggerInterface $triggerClass */ - $triggerClass = new $class($trigger, $this->journal); + $triggerClass = TriggerFactory::getTrigger($trigger, $this->journal); if ($triggerClass->triggered()) { $hitTriggers++; } if ($trigger->stop_processing) { break; } - + } Log::debug('Total: ' . $foundTriggers . ' found triggers. ' . $hitTriggers . ' triggers were hit.'); - + return ($hitTriggers == $foundTriggers); } diff --git a/app/Rules/Triggers/AmountExactly.php b/app/Rules/Triggers/AmountExactly.php index 02045a42f8..03af0bec25 100644 --- a/app/Rules/Triggers/AmountExactly.php +++ b/app/Rules/Triggers/AmountExactly.php @@ -22,12 +22,10 @@ use Log; */ class AmountExactly implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -41,6 +39,18 @@ class AmountExactly implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return false; + } + /** * @return bool */ diff --git a/app/Rules/Triggers/AmountLess.php b/app/Rules/Triggers/AmountLess.php index cfad91f24b..5a9c72976b 100644 --- a/app/Rules/Triggers/AmountLess.php +++ b/app/Rules/Triggers/AmountLess.php @@ -22,12 +22,10 @@ use Log; */ class AmountLess implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -41,6 +39,18 @@ class AmountLess implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return false; + } + /** * @return bool */ diff --git a/app/Rules/Triggers/AmountMore.php b/app/Rules/Triggers/AmountMore.php index a7d6711f1f..27ea6e02c3 100644 --- a/app/Rules/Triggers/AmountMore.php +++ b/app/Rules/Triggers/AmountMore.php @@ -22,12 +22,10 @@ use Log; */ class AmountMore implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -41,6 +39,18 @@ class AmountMore implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return bccomp('0', $this->trigger->trigger_value) === 0; + } + /** * @return bool */ diff --git a/app/Rules/Triggers/DescriptionContains.php b/app/Rules/Triggers/DescriptionContains.php index 4e5fe8428a..e0949a60ee 100644 --- a/app/Rules/Triggers/DescriptionContains.php +++ b/app/Rules/Triggers/DescriptionContains.php @@ -22,12 +22,10 @@ use Log; */ class DescriptionContains implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -41,6 +39,18 @@ class DescriptionContains implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return $this->trigger->trigger_value === ""; + } + /** * @return bool */ diff --git a/app/Rules/Triggers/DescriptionEnds.php b/app/Rules/Triggers/DescriptionEnds.php index b71009799a..406fb385b9 100644 --- a/app/Rules/Triggers/DescriptionEnds.php +++ b/app/Rules/Triggers/DescriptionEnds.php @@ -21,12 +21,10 @@ use Log; */ class DescriptionEnds implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -40,6 +38,18 @@ class DescriptionEnds implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return $this->trigger->trigger_value === ""; + } + /** * @return bool */ @@ -72,4 +82,5 @@ class DescriptionEnds implements TriggerInterface return false; } + } diff --git a/app/Rules/Triggers/DescriptionIs.php b/app/Rules/Triggers/DescriptionIs.php index 12bc48b697..f6cedfd335 100644 --- a/app/Rules/Triggers/DescriptionIs.php +++ b/app/Rules/Triggers/DescriptionIs.php @@ -21,12 +21,10 @@ use Log; */ class DescriptionIs implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -40,6 +38,18 @@ class DescriptionIs implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return false; + } + /** * @return bool */ @@ -58,4 +68,5 @@ class DescriptionIs implements TriggerInterface return false; } + } diff --git a/app/Rules/Triggers/DescriptionStarts.php b/app/Rules/Triggers/DescriptionStarts.php index 9b23e1253c..f5ad96953d 100644 --- a/app/Rules/Triggers/DescriptionStarts.php +++ b/app/Rules/Triggers/DescriptionStarts.php @@ -21,12 +21,10 @@ use Log; */ class DescriptionStarts implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -40,6 +38,18 @@ class DescriptionStarts implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return $this->trigger->trigger_value === ""; + } + /** * @return bool */ @@ -60,4 +70,5 @@ class DescriptionStarts implements TriggerInterface return false; } + } diff --git a/app/Rules/Triggers/FromAccountContains.php b/app/Rules/Triggers/FromAccountContains.php index 05badb6f7b..c7e28041ba 100644 --- a/app/Rules/Triggers/FromAccountContains.php +++ b/app/Rules/Triggers/FromAccountContains.php @@ -21,12 +21,10 @@ use Log; */ class FromAccountContains implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -40,6 +38,18 @@ class FromAccountContains implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return $this->trigger->trigger_value === ""; + } + /** * @return bool */ @@ -62,4 +72,5 @@ class FromAccountContains implements TriggerInterface return false; } + } diff --git a/app/Rules/Triggers/FromAccountEnds.php b/app/Rules/Triggers/FromAccountEnds.php index e4b144bb87..79659fad98 100644 --- a/app/Rules/Triggers/FromAccountEnds.php +++ b/app/Rules/Triggers/FromAccountEnds.php @@ -21,12 +21,10 @@ use Log; */ class FromAccountEnds implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -40,6 +38,18 @@ class FromAccountEnds implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return $this->trigger->trigger_value === ""; + } + /** * @return bool */ @@ -72,4 +82,5 @@ class FromAccountEnds implements TriggerInterface return false; } + } diff --git a/app/Rules/Triggers/FromAccountIs.php b/app/Rules/Triggers/FromAccountIs.php index 9fb084de93..07265484f8 100644 --- a/app/Rules/Triggers/FromAccountIs.php +++ b/app/Rules/Triggers/FromAccountIs.php @@ -21,12 +21,10 @@ use Log; */ class FromAccountIs implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -40,6 +38,18 @@ class FromAccountIs implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return false; + } + /** * @return bool */ @@ -58,4 +68,5 @@ class FromAccountIs implements TriggerInterface return false; } + } diff --git a/app/Rules/Triggers/FromAccountStarts.php b/app/Rules/Triggers/FromAccountStarts.php index 6eea3179f4..7588769ed4 100644 --- a/app/Rules/Triggers/FromAccountStarts.php +++ b/app/Rules/Triggers/FromAccountStarts.php @@ -21,12 +21,10 @@ use Log; */ class FromAccountStarts implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -40,6 +38,18 @@ class FromAccountStarts implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return $this->trigger->trigger_value === ""; + } + /** * @return bool */ @@ -60,4 +70,5 @@ class FromAccountStarts implements TriggerInterface return false; } + } diff --git a/app/Rules/Triggers/ToAccountContains.php b/app/Rules/Triggers/ToAccountContains.php index 06d081bfac..b55d592bec 100644 --- a/app/Rules/Triggers/ToAccountContains.php +++ b/app/Rules/Triggers/ToAccountContains.php @@ -21,12 +21,10 @@ use Log; */ class ToAccountContains implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -40,6 +38,18 @@ class ToAccountContains implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return $this->trigger->trigger_value === ""; + } + /** * @return bool */ @@ -62,4 +72,5 @@ class ToAccountContains implements TriggerInterface return false; } + } diff --git a/app/Rules/Triggers/ToAccountEnds.php b/app/Rules/Triggers/ToAccountEnds.php index 5637df0cb6..0dc9d757c8 100644 --- a/app/Rules/Triggers/ToAccountEnds.php +++ b/app/Rules/Triggers/ToAccountEnds.php @@ -21,12 +21,10 @@ use Log; */ class ToAccountEnds implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -40,6 +38,18 @@ class ToAccountEnds implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return $this->trigger->trigger_value === ""; + } + /** * @return bool */ diff --git a/app/Rules/Triggers/ToAccountIs.php b/app/Rules/Triggers/ToAccountIs.php index 1eb9f5623e..1d389ca5dd 100644 --- a/app/Rules/Triggers/ToAccountIs.php +++ b/app/Rules/Triggers/ToAccountIs.php @@ -21,12 +21,10 @@ use Log; */ class ToAccountIs implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -40,6 +38,18 @@ class ToAccountIs implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return false; + } + /** * @return bool */ @@ -58,4 +68,5 @@ class ToAccountIs implements TriggerInterface return false; } + } diff --git a/app/Rules/Triggers/ToAccountStarts.php b/app/Rules/Triggers/ToAccountStarts.php index 446a592d29..e9d5b8caa7 100644 --- a/app/Rules/Triggers/ToAccountStarts.php +++ b/app/Rules/Triggers/ToAccountStarts.php @@ -21,12 +21,10 @@ use Log; */ class ToAccountStarts implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -40,6 +38,18 @@ class ToAccountStarts implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return $this->trigger->trigger_value === ""; + } + /** * @return bool */ @@ -60,4 +70,5 @@ class ToAccountStarts implements TriggerInterface return false; } + } diff --git a/app/Rules/Triggers/TransactionType.php b/app/Rules/Triggers/TransactionType.php index 1a96720fc8..4a47604a66 100644 --- a/app/Rules/Triggers/TransactionType.php +++ b/app/Rules/Triggers/TransactionType.php @@ -21,12 +21,10 @@ use Log; */ class TransactionType implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -40,6 +38,18 @@ class TransactionType implements TriggerInterface $this->journal = $journal; } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return false; + } + /** * @return bool */ @@ -57,4 +67,5 @@ class TransactionType implements TriggerInterface return false; } + } diff --git a/app/Rules/Triggers/TriggerFactory.php b/app/Rules/Triggers/TriggerFactory.php new file mode 100644 index 0000000000..2eaf47e354 --- /dev/null +++ b/app/Rules/Triggers/TriggerFactory.php @@ -0,0 +1,77 @@ +trigger_type; + $class = self::getTriggerClass($triggerType); + + return new $class($trigger, $journal); + } + + /** + * Returns the class name to be used for triggers with the given name + * + * @param string $triggerType + * + * @return TriggerInterface + */ + public static function getTriggerClass(string $triggerType): string + { + $triggerTypes = self::getTriggerTypes(); + + if (!array_key_exists($triggerType, $triggerTypes)) { + throw new FireflyException('No such trigger exists ("' . e($triggerType) . '").'); + } + + $class = $triggerTypes[$triggerType]; + if (!class_exists($class)) { + throw new FireflyException('Could not instantiate class for rule trigger type "' . e($triggerType) . '" (' . e($class) . ').'); + } + + return $class; + } + + /** + * Returns a map with triggertypes, mapped to the class representing that type + */ + protected static function getTriggerTypes() + { + if (!self::$triggerTypes) { + self::$triggerTypes = Domain::getRuleTriggers(); + } + + return self::$triggerTypes; + } +} diff --git a/app/Rules/Triggers/TriggerInterface.php b/app/Rules/Triggers/TriggerInterface.php index 074cacdd40..2c8f61f4f8 100644 --- a/app/Rules/Triggers/TriggerInterface.php +++ b/app/Rules/Triggers/TriggerInterface.php @@ -28,6 +28,22 @@ interface TriggerInterface */ public function __construct(RuleTrigger $trigger, TransactionJournal $journal); + /** + * A trigger is said to "match anything", or match any given transaction, + * when the trigger value is very vague or has no restrictions. Easy examples + * are the "AmountMore"-trigger combined with an amount of 0: any given transaction + * has an amount of more than zero! Other examples are all the "Description"-triggers + * which have hard time handling empty trigger values such as "" or "*" (wild cards). + * + * If the user tries to create such a trigger, this method MUST return true so Firefly III + * can stop the storing / updating the trigger. If the trigger is in any way restrictive + * (even if it will still include 99.9% of the users transactions), this method MUST return + * false. + * + * @return bool + */ + public function matchesAnything(); + /** * @return bool */ diff --git a/app/Rules/Triggers/UserAction.php b/app/Rules/Triggers/UserAction.php index 917f2d8822..c9fdcc78a2 100644 --- a/app/Rules/Triggers/UserAction.php +++ b/app/Rules/Triggers/UserAction.php @@ -21,12 +21,10 @@ use Log; */ class UserAction implements TriggerInterface { - /** @var RuleTrigger */ - protected $trigger; - /** @var TransactionJournal */ protected $journal; - + /** @var RuleTrigger */ + protected $trigger; /** * TriggerInterface constructor. @@ -41,6 +39,18 @@ class UserAction implements TriggerInterface } + /** + * @{inheritdoc} + * + * @see TriggerInterface::matchesAnything + * + * @return bool + */ + public function matchesAnything() + { + return true; + } + /** * This trigger is always triggered, because the rule that it is a part of has been pre-selected on this condition. * diff --git a/resources/views/rules/index.twig b/resources/views/rules/index.twig index 272ed57928..447cf3d4eb 100644 --- a/resources/views/rules/index.twig +++ b/resources/views/rules/index.twig @@ -46,17 +46,16 @@