2020-12-02 06:54:13 +01:00
< ? php
2021-08-10 19:31:55 +02:00
2020-12-02 06:54:13 +01:00
/*
2021-08-10 19:31:55 +02:00
* StandardMessageGenerator . php
* Copyright ( c ) 2021 james @ firefly - iii . org
2020-12-02 06:54:13 +01:00
*
* 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 />.
*/
2021-08-10 19:31:55 +02:00
declare ( strict_types = 1 );
2020-12-02 06:54:13 +01:00
namespace FireflyIII\Generator\Webhook ;
2022-09-17 16:54:13 +02:00
use FireflyIII\Enums\WebhookResponse ;
use FireflyIII\Enums\WebhookTrigger ;
2020-12-02 06:54:13 +01:00
use FireflyIII\Exceptions\FireflyException ;
2025-08-18 20:01:22 +02:00
use FireflyIII\Models\Budget ;
use FireflyIII\Models\BudgetLimit ;
2020-12-02 06:54:13 +01:00
use FireflyIII\Models\Transaction ;
2025-08-20 06:32:25 +02:00
use FireflyIII\Models\WebhookResponse as WebhookResponseModel ;
2020-12-02 06:54:13 +01:00
use FireflyIII\Models\TransactionGroup ;
use FireflyIII\Models\TransactionJournal ;
use FireflyIII\Models\Webhook ;
use FireflyIII\Models\WebhookMessage ;
2025-07-01 19:31:27 +02:00
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment ;
2025-08-18 20:01:22 +02:00
use FireflyIII\Support\JsonApi\Enrichments\BudgetEnrichment ;
use FireflyIII\Support\JsonApi\Enrichments\BudgetLimitEnrichment ;
2020-12-02 06:54:13 +01:00
use FireflyIII\Transformers\AccountTransformer ;
2025-08-18 20:01:22 +02:00
use FireflyIII\Transformers\BudgetLimitTransformer ;
use FireflyIII\Transformers\BudgetTransformer ;
2020-12-02 06:54:13 +01:00
use FireflyIII\Transformers\TransactionGroupTransformer ;
use FireflyIII\User ;
2020-12-05 06:47:16 +01:00
use Illuminate\Database\Eloquent\Model ;
2020-12-02 06:54:13 +01:00
use Illuminate\Support\Collection ;
2025-07-01 19:31:27 +02:00
use Illuminate\Support\Facades\Log ;
2020-12-02 06:54:13 +01:00
use Ramsey\Uuid\Uuid ;
use Symfony\Component\HttpFoundation\ParameterBag ;
/**
2020-12-04 20:19:52 +01:00
* Class StandardMessageGenerator
2020-12-02 06:54:13 +01:00
*/
2020-12-04 20:19:52 +01:00
class StandardMessageGenerator implements MessageGeneratorInterface
2020-12-02 06:54:13 +01:00
{
2025-08-17 07:40:19 +02:00
private Collection $objects ;
private WebhookTrigger $trigger ;
private User $user ;
private int $version = 0 ;
private Collection $webhooks ;
2020-12-02 06:54:13 +01:00
2023-01-05 19:05:23 +01:00
public function __construct ()
{
$this -> objects = new Collection ();
$this -> webhooks = new Collection ();
}
2020-12-02 06:54:13 +01:00
public function generateMessages () : void
{
2025-07-01 19:31:27 +02:00
Log :: debug ( __METHOD__ );
2020-12-05 06:47:16 +01:00
// get the webhooks:
2023-01-05 19:05:23 +01:00
if ( 0 === $this -> webhooks -> count ()) {
$this -> webhooks = $this -> getWebhooks ();
}
2020-12-05 06:47:16 +01:00
// do some debugging
2025-08-17 07:40:19 +02:00
Log :: debug ( sprintf ( 'StandardMessageGenerator will generate messages for %d object(s) and %d webhook(s).' , $this -> objects -> count (), $this -> webhooks -> count ()));
2020-12-02 06:54:13 +01:00
$this -> run ();
}
2023-06-21 12:34:58 +02:00
private function getWebhooks () : Collection
2023-05-29 13:56:55 +02:00
{
2023-06-21 12:34:58 +02:00
return $this -> user -> webhooks () -> where ( 'active' , true ) -> where ( 'trigger' , $this -> trigger ) -> get ([ 'webhooks.*' ]);
2023-05-29 13:56:55 +02:00
}
2025-08-17 07:40:19 +02:00
/**
* @ throws FireflyException
*/
2023-06-21 12:34:58 +02:00
private function run () : void
2023-05-29 13:56:55 +02:00
{
2025-07-01 19:31:27 +02:00
Log :: debug ( 'Now in StandardMessageGenerator::run' );
2023-12-20 19:35:52 +01:00
2023-06-21 12:34:58 +02:00
/** @var Webhook $webhook */
foreach ( $this -> webhooks as $webhook ) {
$this -> runWebhook ( $webhook );
}
2025-07-01 19:31:27 +02:00
Log :: debug ( 'Done with StandardMessageGenerator::run' );
2023-05-29 13:56:55 +02:00
}
/**
2023-06-21 12:34:58 +02:00
* @ throws FireflyException
2023-12-22 20:12:38 +01:00
*/
2023-06-21 12:34:58 +02:00
private function runWebhook ( Webhook $webhook ) : void
2023-05-29 13:56:55 +02:00
{
2025-07-01 19:31:27 +02:00
Log :: debug ( sprintf ( 'Now in runWebhook(#%d)' , $webhook -> id ));
2023-12-20 19:35:52 +01:00
2023-06-21 12:34:58 +02:00
/** @var Model $object */
foreach ( $this -> objects as $object ) {
$this -> generateMessage ( $webhook , $object );
2020-12-02 06:54:13 +01:00
}
}
/**
2022-03-29 15:10:05 +02:00
* @ throws FireflyException
2023-12-22 20:12:38 +01:00
*/
2020-12-05 06:47:16 +01:00
private function generateMessage ( Webhook $webhook , Model $model ) : void
2020-12-02 06:54:13 +01:00
{
2025-08-18 20:08:18 +02:00
$class = $model :: class ;
2022-12-31 06:57:05 +01:00
// Line is ignored because all of Firefly III's Models have an id property.
2025-07-01 19:31:27 +02:00
Log :: debug ( sprintf ( 'Now in generateMessage(#%d, %s#%d)' , $webhook -> id , $class , $model -> id ));
2020-12-05 06:47:16 +01:00
$uuid = Uuid :: uuid4 ();
$basicMessage = [
2025-08-17 11:08:00 +02:00
'uuid' => $uuid -> toString (),
'user_id' => 0 ,
2025-08-17 07:40:19 +02:00
'user_group_id' => 0 ,
2025-08-20 06:32:25 +02:00
'trigger' => $this -> trigger -> name ,
'response' => $webhook -> webhookResponses () -> first () -> title , // guess that the database is correct.
2025-08-17 11:08:00 +02:00
'url' => $webhook -> url ,
'version' => sprintf ( 'v%d' , $this -> getVersion ()),
'content' => [],
2020-12-02 06:54:13 +01:00
];
2020-12-05 06:47:16 +01:00
// depends on the model how user_id is set:
2025-08-20 06:32:25 +02:00
$relevantResponse = WebhookResponse :: TRANSACTIONS -> name ;
2020-12-05 06:47:16 +01:00
switch ( $class ) {
default :
2022-12-31 06:57:05 +01:00
// Line is ignored because all of Firefly III's Models have an id property.
2025-08-17 07:40:19 +02:00
Log :: error ( sprintf ( 'Webhook #%d was given %s#%d to deal with but can\'t extract user ID from it.' , $webhook -> id , $class , $model -> id ));
2020-12-05 06:47:16 +01:00
return ;
2025-08-18 20:08:18 +02:00
2025-08-18 20:01:22 +02:00
case Budget :: class :
/** @var Budget $model */
$basicMessage [ 'user_id' ] = $model -> user_id ;
$basicMessage [ 'user_group_id' ] = $model -> user_group_id ;
2025-08-20 06:32:25 +02:00
$relevantResponse = WebhookResponse :: BUDGET -> name ;
2025-08-18 20:08:18 +02:00
2025-08-18 20:01:22 +02:00
break ;
2025-08-18 20:08:18 +02:00
2025-08-18 20:01:22 +02:00
case BudgetLimit :: class :
$basicMessage [ 'user_id' ] = $model -> budget -> user_id ;
$basicMessage [ 'user_group_id' ] = $model -> budget -> user_group_id ;
2025-08-20 06:32:25 +02:00
$relevantResponse = WebhookResponse :: BUDGET -> name ;
2025-08-18 20:08:18 +02:00
2025-08-18 20:01:22 +02:00
break ;
2025-08-18 20:08:18 +02:00
2020-12-05 06:47:16 +01:00
case TransactionGroup :: class :
2025-01-04 07:10:37 +01:00
/** @var TransactionGroup $model */
2025-08-17 11:08:00 +02:00
$basicMessage [ 'user_id' ] = $model -> user_id ;
2025-08-17 07:40:19 +02:00
$basicMessage [ 'user_group_id' ] = $model -> user_group_id ;
2023-12-20 19:35:52 +01:00
2020-12-05 06:47:16 +01:00
break ;
}
// then depends on the response what to put in the message:
2025-08-20 06:32:25 +02:00
/** @var WebhookResponseModel $response */
$model = $webhook -> webhookResponses () -> first ();
$response = $model -> title ;
// if it's relevant, just switch to another.
if ( WebhookResponse :: RELEVANT -> name === $response ) {
// switch to whatever is actually relevant.
$response = $relevantResponse ;
}
switch ( $response ) {
2020-12-02 06:54:13 +01:00
default :
2025-08-17 07:40:19 +02:00
Log :: error ( sprintf ( 'The response code for webhook #%d is "%d" and the message generator cant handle it. Soft fail.' , $webhook -> id , $webhook -> response ));
2020-12-04 20:19:52 +01:00
return ;
2025-08-18 20:08:18 +02:00
case WebhookResponse :: BUDGET -> value :
2025-08-18 20:01:22 +02:00
$basicMessage [ 'content' ] = [];
2025-08-18 20:08:18 +02:00
if ( $model instanceof Budget ) {
$enrichment = new BudgetEnrichment ();
$enrichment -> setUser ( $model -> user );
$model = $enrichment -> enrichSingle ( $model );
$transformer = new BudgetTransformer ();
$basicMessage [ 'content' ] = $transformer -> transform ( $model );
}
if ( $model instanceof BudgetLimit ) {
$user = $model -> budget -> user ;
$enrichment = new BudgetLimitEnrichment ();
2025-08-18 20:01:22 +02:00
$enrichment -> setUser ( $user );
2025-08-18 20:08:18 +02:00
$parameters = new ParameterBag ();
2025-08-18 20:01:22 +02:00
$parameters -> set ( 'start' , $model -> start_date );
$parameters -> set ( 'end' , $model -> end_date );
$model = $enrichment -> enrichSingle ( $model );
$transformer = new BudgetLimitTransformer ();
$transformer -> setParameters ( $parameters );
$basicMessage [ 'content' ] = $transformer -> transform ( $model );
}
2025-08-18 20:08:18 +02:00
2025-08-18 20:01:22 +02:00
break ;
2023-12-20 19:35:52 +01:00
2022-09-17 16:54:13 +02:00
case WebhookResponse :: NONE -> value :
2020-12-05 06:47:16 +01:00
$basicMessage [ 'content' ] = [];
2023-12-20 19:35:52 +01:00
2020-12-04 20:19:52 +01:00
break ;
2023-12-20 19:35:52 +01:00
2022-09-17 16:54:13 +02:00
case WebhookResponse :: TRANSACTIONS -> value :
2023-12-21 04:59:23 +01:00
/** @var TransactionGroup $model */
2025-08-18 20:08:18 +02:00
$transformer = new TransactionGroupTransformer ();
2023-12-20 19:35:52 +01:00
2020-12-04 20:19:52 +01:00
try {
2020-12-05 06:47:16 +01:00
$basicMessage [ 'content' ] = $transformer -> transformObject ( $model );
2020-12-04 20:19:52 +01:00
} catch ( FireflyException $e ) {
2025-07-01 19:31:27 +02:00
Log :: error (
2020-12-05 06:47:16 +01:00
sprintf ( 'The transformer could not include the requested transaction group for webhook #%d: %s' , $webhook -> id , $e -> getMessage ())
);
2025-07-01 19:31:27 +02:00
Log :: error ( $e -> getTraceAsString ());
2020-12-05 06:47:16 +01:00
return ;
2020-12-04 20:19:52 +01:00
}
2023-12-20 19:35:52 +01:00
2020-12-02 06:54:13 +01:00
break ;
2023-12-20 19:35:52 +01:00
2022-09-17 16:54:13 +02:00
case WebhookResponse :: ACCOUNTS -> value :
2023-12-21 04:59:23 +01:00
/** @var TransactionGroup $model */
2025-08-18 20:08:18 +02:00
$accounts = $this -> collectAccounts ( $model );
$enrichment = new AccountEnrichment ();
2025-08-03 10:22:12 +02:00
$enrichment -> setDate ( null );
2025-07-01 19:31:27 +02:00
$enrichment -> setUser ( $model -> user );
2025-08-18 20:08:18 +02:00
$accounts = $enrichment -> enrich ( $accounts );
2020-12-02 06:54:13 +01:00
foreach ( $accounts as $account ) {
2025-08-18 20:08:18 +02:00
$transformer = new AccountTransformer ();
2022-10-30 14:24:10 +01:00
$transformer -> setParameters ( new ParameterBag ());
2020-12-05 06:47:16 +01:00
$basicMessage [ 'content' ][] = $transformer -> transform ( $account );
2020-12-02 06:54:13 +01:00
}
}
2020-12-05 06:47:16 +01:00
$this -> storeMessage ( $webhook , $basicMessage );
2020-12-02 06:54:13 +01:00
}
2024-03-06 07:16:01 +01:00
public function getVersion () : int
{
return $this -> version ;
}
2023-06-21 12:34:58 +02:00
private function collectAccounts ( TransactionGroup $transactionGroup ) : Collection
2020-12-02 06:54:13 +01:00
{
2023-06-21 12:34:58 +02:00
$accounts = new Collection ();
2023-12-20 19:35:52 +01:00
2023-06-21 12:34:58 +02:00
/** @var TransactionJournal $journal */
foreach ( $transactionGroup -> transactionJournals as $journal ) {
/** @var Transaction $transaction */
foreach ( $journal -> transactions as $transaction ) {
$accounts -> push ( $transaction -> account );
}
2020-12-02 06:54:13 +01:00
}
2023-06-21 12:34:58 +02:00
return $accounts -> unique ();
2020-12-02 06:54:13 +01:00
}
2022-03-29 15:10:05 +02:00
private function storeMessage ( Webhook $webhook , array $message ) : void
2020-12-02 06:54:13 +01:00
{
2025-08-18 20:08:18 +02:00
$webhookMessage = new WebhookMessage ();
2020-12-02 06:54:13 +01:00
$webhookMessage -> webhook () -> associate ( $webhook );
$webhookMessage -> sent = false ;
$webhookMessage -> errored = false ;
$webhookMessage -> uuid = $message [ 'uuid' ];
$webhookMessage -> message = $message ;
$webhookMessage -> save ();
2025-07-01 19:31:27 +02:00
Log :: debug ( sprintf ( 'Stored new webhook message #%d' , $webhookMessage -> id ));
2020-12-02 06:54:13 +01:00
}
2024-03-06 07:16:01 +01:00
public function setObjects ( Collection $objects ) : void
{
$this -> objects = $objects ;
}
2025-08-17 07:40:19 +02:00
public function setTrigger ( WebhookTrigger $trigger ) : void
2024-03-06 07:16:01 +01:00
{
$this -> trigger = $trigger ;
}
public function setUser ( User $user ) : void
{
$this -> user = $user ;
}
public function setWebhooks ( Collection $webhooks ) : void
{
$this -> webhooks = $webhooks ;
}
2020-12-22 05:35:06 +01:00
}