New triggers and actions for notes. #872

This commit is contained in:
James Cole 2017-10-03 05:28:00 +02:00
parent 7a57c60891
commit 95b5793f63
No known key found for this signature in database
GPG Key ID: C16961E655E74B5E
13 changed files with 1209 additions and 494 deletions

View File

@ -0,0 +1,55 @@
<?php
/**
* AppendNotes.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal;
use Log;
/**
* Class AppendNotes
*
* @package FireflyIII\TransactionRules\Actions
*/
class AppendNotes implements ActionInterface
{
private $action;
/**
* TriggerInterface constructor.
*
* @param RuleAction $action
*/
public function __construct(RuleAction $action)
{
$this->action = $action;
}
/**
* @param TransactionJournal $journal
*
* @return bool
*/
public function act(TransactionJournal $journal): bool
{
$notes = $journal->getMeta('notes');
Log::debug(sprintf('RuleAction AppendNotes appended "%s" to "%s".', $this->action->action_value, $notes));
$notes = $notes . $this->action->action_value;
$journal->setMeta('notes', $notes);
$journal->save();
return true;
}
}

View File

@ -0,0 +1,53 @@
<?php
/**
* ClearNotes.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal;
use Log;
/**
* Class ClearNotes
*
* @package FireflyIII\TransactionRules\Actions
*/
class ClearNotes implements ActionInterface
{
private $action;
/**
* TriggerInterface constructor.
*
* @param RuleAction $action
*/
public function __construct(RuleAction $action)
{
$this->action = $action;
}
/**
* @param TransactionJournal $journal
*
* @return bool
*/
public function act(TransactionJournal $journal): bool
{
Log::debug(sprintf('RuleAction ClearNotes removed all notes.'));
$journal->deleteMeta('notes');
$journal->save();
return true;
}
}

View File

@ -0,0 +1,55 @@
<?php
/**
* PrependNotes.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal;
use Log;
/**
* Class PrependNotes
*
* @package FireflyIII\TransactionRules\Actions
*/
class PrependNotes implements ActionInterface
{
private $action;
/**
* TriggerInterface constructor.
*
* @param RuleAction $action
*/
public function __construct(RuleAction $action)
{
$this->action = $action;
}
/**
* @param TransactionJournal $journal
*
* @return bool
*/
public function act(TransactionJournal $journal): bool
{
$notes = $journal->getMeta('notes');
Log::debug(sprintf('RuleAction PrependNotes prepended "%s" with "%s".', $notes, $this->action->action_value));
$notes = $this->action->action_value . $notes;
$journal->setMeta('notes', $notes);
$journal->save();
return true;
}
}

View File

@ -0,0 +1,56 @@
<?php
/**
* SetNotes.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\TransactionJournal;
use Log;
/**
* Class SetNotes
*
* @package FireflyIII\TransactionRules\Actions
*/
class SetNotes implements ActionInterface
{
private $action;
/**
* TriggerInterface constructor.
*
* @param RuleAction $action
*/
public function __construct(RuleAction $action)
{
$this->action = $action;
}
/**
* @param TransactionJournal $journal
*
* @return bool
*/
public function act(TransactionJournal $journal): bool
{
$oldNotes = $journal->getMeta('notes');
$journal->setMeta('notes', $this->action->action_value);
$journal->save();
Log::debug(sprintf('RuleAction SetNotes changed the notes of journal #%d from "%s" to "%s".', $journal->id, $oldNotes, $this->action->action_value));
return true;
}
}

View File

@ -0,0 +1,67 @@
<?php
/**
* NotesAny.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\TransactionRules\Triggers;
use FireflyIII\Models\TransactionJournal;
use Log;
/**
* Class NotesAny
*
* @package FireflyIII\TransactionRules\Triggers
*/
final class NotesAny extends AbstractTrigger implements TriggerInterface
{
/**
* 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.
*
* @param null $value
*
* @return bool
*/
public static function willMatchEverything($value = null)
{
return false;
}
/**
* @param TransactionJournal $journal
*
* @return bool
*/
public function triggered(TransactionJournal $journal): bool
{
$notes = $journal->getMeta('notes') ?? '';
if (strlen($notes) > 0) {
Log::debug(sprintf('RuleTrigger NotesEmpty for journal #%d: strlen > 0, return true.', $journal->id));
return true;
}
Log::debug(sprintf('RuleTrigger NotesEmpty for journal #%d: strlen is 0, return false.', $journal->id));
return false;
}
}

View File

@ -0,0 +1,74 @@
<?php
/**
* NotesAre.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\TransactionRules\Triggers;
use FireflyIII\Models\TransactionJournal;
use Log;
/**
* Class NotesAre
*
* @package FireflyIII\TransactionRules\Triggers
*/
final class NotesAre extends AbstractTrigger implements TriggerInterface
{
/**
* 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.
*
* @param null $value
*
* @return bool
*/
public static function willMatchEverything($value = null)
{
if (!is_null($value)) {
return false;
}
Log::error(sprintf('Cannot use %s with a null value.', self::class));
return true;
}
/**
* @param TransactionJournal $journal
*
* @return bool
*/
public function triggered(TransactionJournal $journal): bool
{
$notes = strtolower($journal->getMeta('notes') ?? '');
$search = strtolower($this->triggerValue);
if ($notes === $search) {
Log::debug(sprintf('RuleTrigger NotesAre for journal #%d: "%s" is "%s", return true.', $journal->id, $notes, $search));
return true;
}
Log::debug(sprintf('RuleTrigger NotesAre for journal #%d: "%s" is NOT "%s", return false.', $journal->id, $notes, $search));
return false;
}
}

View File

@ -0,0 +1,82 @@
<?php
/**
* NotesContain.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\TransactionRules\Triggers;
use FireflyIII\Models\TransactionJournal;
use Log;
/**
* Class NotesContain
*
* @package FireflyIII\TransactionRules\Triggers
*/
final class NotesContain extends AbstractTrigger implements TriggerInterface
{
/**
* 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.
*
* @param null $value
*
* @return bool
*/
public static function willMatchEverything($value = null)
{
if (!is_null($value)) {
$res = strval($value) === '';
if ($res === true) {
Log::error(sprintf('Cannot use %s with "" as a value.', self::class));
}
return $res;
}
Log::error(sprintf('Cannot use %s with a null value.', self::class));
return true;
}
/**
* @param TransactionJournal $journal
*
* @return bool
*/
public function triggered(TransactionJournal $journal): bool
{
$search = strtolower($this->triggerValue);
$notes = strtolower($journal->getMeta('notes') ?? '');
$strpos = strpos($notes, $search);
if (!($strpos === false)) {
Log::debug(sprintf('RuleTrigger NotesContain for journal #%d: "%s" contains "%s", return true.', $journal->id, $notes, $search));
return true;
}
Log::debug(sprintf('RuleTrigger NotesContain for journal #%d: "%s" does NOT contain "%s", return false.', $journal->id, $notes, $search));
return false;
}
}

View File

@ -0,0 +1,67 @@
<?php
/**
* NotesEmpty.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\TransactionRules\Triggers;
use FireflyIII\Models\TransactionJournal;
use Log;
/**
* Class NotesEmpty
*
* @package FireflyIII\TransactionRules\Triggers
*/
final class NotesEmpty extends AbstractTrigger implements TriggerInterface
{
/**
* 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.
*
* @param null $value
*
* @return bool
*/
public static function willMatchEverything($value = null)
{
return false;
}
/**
* @param TransactionJournal $journal
*
* @return bool
*/
public function triggered(TransactionJournal $journal): bool
{
$notes = $journal->getMeta('notes') ?? '';
if (strlen($notes) === 0) {
Log::debug(sprintf('RuleTrigger NotesEmpty for journal #%d: strlen is 0, return true.', $journal->id));
return true;
}
Log::debug(sprintf('RuleTrigger NotesEmpty for journal #%d: strlen > 0, return false.', $journal->id));
return false;
}
}

View File

@ -0,0 +1,90 @@
<?php
/**
* NotesEnd.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\TransactionRules\Triggers;
use FireflyIII\Models\TransactionJournal;
use Log;
/**
* Class NotesEnd
*
* @package FireflyIII\TransactionRules\Triggers
*/
final class NotesEnd extends AbstractTrigger implements TriggerInterface
{
/**
* 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.
*
* @param null $value
*
* @return bool
*/
public static function willMatchEverything($value = null)
{
if (!is_null($value)) {
$res = strval($value) === '';
if ($res === true) {
Log::error(sprintf('Cannot use %s with "" as a value.', self::class));
}
return $res;
}
Log::error(sprintf('Cannot use %s with a null value.', self::class));
return true;
}
/**
* @param TransactionJournal $journal
*
* @return bool
*/
public function triggered(TransactionJournal $journal): bool
{
$notes = strtolower($journal->getMeta('notes') ?? '');
$notesLength = strlen($notes);
$search = strtolower($this->triggerValue);
$searchLength = strlen($search);
// if the string to search for is longer than the description,
// shorten the search string.
if ($searchLength > $notesLength) {
$search = substr($search, ($notesLength * -1));
$searchLength = strlen($search);
}
$part = substr($notes, $searchLength * -1);
if ($part === $search) {
Log::debug(sprintf('RuleTrigger NotesEnd for journal #%d: "%s" ends with "%s", return true.', $journal->id, $notes, $search));
return true;
}
Log::debug(sprintf('RuleTrigger NotesEnd for journal #%d: "%s" does not end with "%s", return false.', $journal->id, $notes, $search));
return false;
}
}

View File

@ -0,0 +1,82 @@
<?php
/**
* NotesStart.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\TransactionRules\Triggers;
use FireflyIII\Models\TransactionJournal;
use Log;
/**
* Class NotesStart
*
* @package FireflyIII\TransactionRules\Triggers
*/
final class NotesStart extends AbstractTrigger implements TriggerInterface
{
/**
* 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.
*
* @param null $value
*
* @return bool
*/
public static function willMatchEverything($value = null)
{
if (!is_null($value)) {
$res = strval($value) === '';
if ($res === true) {
Log::error(sprintf('Cannot use %s with "" as a value.', self::class));
}
return $res;
}
Log::error(sprintf('Cannot use %s with a null value.', self::class));
return true;
}
/**
* @param TransactionJournal $journal
*
* @return bool
*/
public function triggered(TransactionJournal $journal): bool
{
$notes = strtolower($journal->getMeta('notes') ?? '');
$search = strtolower($this->triggerValue);
$part = substr($notes, 0, strlen($search));
if ($part === $search) {
Log::debug(sprintf('RuleTrigger NotesStart for journal #%d: "%s" starts with "%s", return true.', $journal->id, $notes, $search));
return true;
}
Log::debug(sprintf('RuleTrigger NotesStart for journal #%d: "%s" does not start with "%s", return false.', $journal->id, $notes, $search));
return false;
}
}

View File

@ -200,21 +200,30 @@ return [
'has_any_budget' => 'FireflyIII\TransactionRules\Triggers\HasAnyBudget', 'has_any_budget' => 'FireflyIII\TransactionRules\Triggers\HasAnyBudget',
'has_no_tag' => 'FireflyIII\TransactionRules\Triggers\HasNoTag', 'has_no_tag' => 'FireflyIII\TransactionRules\Triggers\HasNoTag',
'has_any_tag' => 'FireflyIII\TransactionRules\Triggers\HasAnyTag', 'has_any_tag' => 'FireflyIII\TransactionRules\Triggers\HasAnyTag',
'notes_contain' => 'FireflyIII\TransactionRules\Triggers\NotesContain',
'notes_start' => 'FireflyIII\TransactionRules\Triggers\NotesStart',
'notes_end' => 'FireflyIII\TransactionRules\Triggers\NotesEnd',
'notes_are' => 'FireflyIII\TransactionRules\Triggers\NotesAre',
'no_notes' => 'FireflyIII\TransactionRules\Triggers\NotesEmpty',
'any_notes' => 'FireflyIII\TransactionRules\Triggers\NotesAny',
], ],
'rule-actions' => [ 'rule-actions' => [
'set_category' => 'FireflyIII\TransactionRules\Actions\SetCategory', 'set_category' => 'FireflyIII\TransactionRules\Actions\SetCategory',
'clear_category' => 'FireflyIII\TransactionRules\Actions\ClearCategory', 'clear_category' => 'FireflyIII\TransactionRules\Actions\ClearCategory',
'set_budget' => 'FireflyIII\TransactionRules\Actions\SetBudget', 'set_budget' => 'FireflyIII\TransactionRules\Actions\SetBudget',
'clear_budget' => 'FireflyIII\TransactionRules\Actions\ClearBudget', 'clear_budget' => 'FireflyIII\TransactionRules\Actions\ClearBudget',
'add_tag' => 'FireflyIII\TransactionRules\Actions\AddTag', 'add_tag' => 'FireflyIII\TransactionRules\Actions\AddTag',
'remove_tag' => 'FireflyIII\TransactionRules\Actions\RemoveTag', 'remove_tag' => 'FireflyIII\TransactionRules\Actions\RemoveTag',
'remove_all_tags' => 'FireflyIII\TransactionRules\Actions\RemoveAllTags', 'remove_all_tags' => 'FireflyIII\TransactionRules\Actions\RemoveAllTags',
'set_description' => 'FireflyIII\TransactionRules\Actions\SetDescription', 'set_description' => 'FireflyIII\TransactionRules\Actions\SetDescription',
'append_description' => 'FireflyIII\TransactionRules\Actions\AppendDescription', 'append_description' => 'FireflyIII\TransactionRules\Actions\AppendDescription',
'prepend_description' => 'FireflyIII\TransactionRules\Actions\PrependDescription', 'prepend_description' => 'FireflyIII\TransactionRules\Actions\PrependDescription',
'set_source_account' => 'FireflyIII\TransactionRules\Actions\SetSourceAccount', 'set_source_account' => 'FireflyIII\TransactionRules\Actions\SetSourceAccount',
'set_destination_account' => 'FireflyIII\TransactionRules\Actions\SetDestinationAccount', 'set_destination_account' => 'FireflyIII\TransactionRules\Actions\SetDestinationAccount',
'set_notes' => 'FireflyIII\TransactionRules\Actions\SetNotes',
'append_notes' => 'FireflyIII\TransactionRules\Actions\AppendNotes',
'prepend_notes' => 'FireflyIII\TransactionRules\Actions\PrependNotes',
'clear_notes' => 'FireflyIII\TransactionRules\Actions\ClearNotes',
], ],
'rule-actions-text' => [ 'rule-actions-text' => [
'set_category', 'set_category',

View File

@ -194,6 +194,7 @@ function updateActionInput(selectList) {
break; break;
case 'clear_category': case 'clear_category':
case 'clear_budget': case 'clear_budget':
case 'clear_notes':
case 'remove_all_tags': case 'remove_all_tags':
input.attr('disabled', 'disabled'); input.attr('disabled', 'disabled');
break; break;
@ -265,6 +266,8 @@ function updateTriggerInput(selectList) {
case 'has_no_budget': case 'has_no_budget':
case 'has_any_budget': case 'has_any_budget':
case 'has_no_tag': case 'has_no_tag':
case 'no_notes':
case 'any_notes':
case 'has_any_tag': case 'has_any_tag':
input.prop('disabled', true); input.prop('disabled', true);
input.typeahead('destroy'); input.typeahead('destroy');

File diff suppressed because it is too large Load Diff