mirror of
https://github.com/grocy/grocy.git
synced 2026-03-28 07:39:25 +01:00
Begin refactoring WebhookRunner into WebhookService
The plan is to enable multiple webhooks to be called for different events which will allow integration with other services without having to poll for changes.
This commit is contained in:
parent
c05181aa53
commit
6b833d178d
|
|
@ -18,6 +18,7 @@ use Grocy\Services\StockService;
|
|||
use Grocy\Services\TasksService;
|
||||
use Grocy\Services\UserfieldsService;
|
||||
use Grocy\Services\UsersService;
|
||||
use Grocy\Services\WebhookService;
|
||||
use DI\Container;
|
||||
|
||||
class BaseController
|
||||
|
|
@ -116,6 +117,11 @@ class BaseController
|
|||
return UsersService::getInstance();
|
||||
}
|
||||
|
||||
protected function getWebhookService()
|
||||
{
|
||||
return WebhookService::getInstance();
|
||||
}
|
||||
|
||||
protected function render($response, $viewName, $data = [])
|
||||
{
|
||||
$container = $this->AppContainer;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
namespace Grocy\Controllers;
|
||||
|
||||
use Grocy\Controllers\Users\User;
|
||||
use Grocy\Helpers\WebhookRunner;
|
||||
use Grocy\Helpers\Grocycode;
|
||||
use Grocy\Services\WebhookService;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
|
|
@ -71,15 +71,12 @@ class BatteriesApiController extends BaseApiController
|
|||
{
|
||||
$battery = $this->getDatabase()->batteries()->where('id', $args['batteryId'])->fetch();
|
||||
|
||||
$webhookData = array_merge([
|
||||
$webhookData = [
|
||||
'battery' => $battery->name,
|
||||
'grocycode' => (string)(new Grocycode(Grocycode::BATTERY, $args['batteryId'])),
|
||||
], GROCY_LABEL_PRINTER_PARAMS);
|
||||
];
|
||||
|
||||
if (GROCY_LABEL_PRINTER_RUN_SERVER)
|
||||
{
|
||||
(new WebhookRunner())->run(GROCY_LABEL_PRINTER_WEBHOOK, $webhookData, GROCY_LABEL_PRINTER_HOOK_JSON);
|
||||
}
|
||||
$this->getWebhookService()->run(WebhookService::EVENT_BATTERY_PRINT_LABEL, $webhookData);
|
||||
|
||||
return $this->ApiResponse($response, $webhookData);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
namespace Grocy\Controllers;
|
||||
|
||||
use Grocy\Controllers\Users\User;
|
||||
use Grocy\Helpers\WebhookRunner;
|
||||
use Grocy\Helpers\Grocycode;
|
||||
use Grocy\Services\WebhookService;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
|
|
@ -122,15 +122,12 @@ class ChoresApiController extends BaseApiController
|
|||
{
|
||||
$chore = $this->getDatabase()->chores()->where('id', $args['choreId'])->fetch();
|
||||
|
||||
$webhookData = array_merge([
|
||||
$webhookData = [
|
||||
'chore' => $chore->name,
|
||||
'grocycode' => (string)(new Grocycode(Grocycode::CHORE, $args['choreId'])),
|
||||
], GROCY_LABEL_PRINTER_PARAMS);
|
||||
];
|
||||
|
||||
if (GROCY_LABEL_PRINTER_RUN_SERVER)
|
||||
{
|
||||
(new WebhookRunner())->run(GROCY_LABEL_PRINTER_WEBHOOK, $webhookData, GROCY_LABEL_PRINTER_HOOK_JSON);
|
||||
}
|
||||
$this->getWebhookService()->run(WebhookService::EVENT_CHORE_PRINT_LABEL, $webhookData);
|
||||
|
||||
return $this->ApiResponse($response, $webhookData);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
namespace Grocy\Controllers;
|
||||
|
||||
use Grocy\Controllers\Users\User;
|
||||
use Grocy\Helpers\WebhookRunner;
|
||||
use Grocy\Helpers\Grocycode;
|
||||
use Grocy\Services\WebhookService;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
|
|
@ -87,15 +87,12 @@ class RecipesApiController extends BaseApiController
|
|||
{
|
||||
$recipe = $this->getDatabase()->recipes()->where('id', $args['recipeId'])->fetch();
|
||||
|
||||
$webhookData = array_merge([
|
||||
$webhookData = [
|
||||
'recipe' => $recipe->name,
|
||||
'grocycode' => (string)(new Grocycode(Grocycode::RECIPE, $args['recipeId'])),
|
||||
], GROCY_LABEL_PRINTER_PARAMS);
|
||||
];
|
||||
|
||||
if (GROCY_LABEL_PRINTER_RUN_SERVER)
|
||||
{
|
||||
(new WebhookRunner())->run(GROCY_LABEL_PRINTER_WEBHOOK, $webhookData, GROCY_LABEL_PRINTER_HOOK_JSON);
|
||||
}
|
||||
$this->getWebhookService()->run(WebhookService::EVENT_RECIPE_PRINT_LABEL, $webhookData);
|
||||
|
||||
return $this->ApiResponse($response, $webhookData);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ namespace Grocy\Controllers;
|
|||
|
||||
use Grocy\Controllers\Users\User;
|
||||
use Grocy\Services\StockService;
|
||||
use Grocy\Helpers\WebhookRunner;
|
||||
use Grocy\Services\WebhookService;
|
||||
use Grocy\Helpers\Grocycode;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
|
@ -674,15 +674,12 @@ class StockApiController extends BaseApiController
|
|||
{
|
||||
$product = $this->getDatabase()->products()->where('id', $args['productId'])->fetch();
|
||||
|
||||
$webhookData = array_merge([
|
||||
$webhookData = [
|
||||
'product' => $product->name,
|
||||
'grocycode' => (string)(new Grocycode(Grocycode::PRODUCT, $product->id)),
|
||||
], GROCY_LABEL_PRINTER_PARAMS);
|
||||
];
|
||||
|
||||
if (GROCY_LABEL_PRINTER_RUN_SERVER)
|
||||
{
|
||||
(new WebhookRunner())->run(GROCY_LABEL_PRINTER_WEBHOOK, $webhookData, GROCY_LABEL_PRINTER_HOOK_JSON);
|
||||
}
|
||||
$this->getWebhookService()->run(WebhookService::EVENT_PRODUCT_PRINT_LABEL, $webhookData);
|
||||
|
||||
return $this->ApiResponse($response, $webhookData);
|
||||
}
|
||||
|
|
@ -699,20 +696,17 @@ class StockApiController extends BaseApiController
|
|||
$stockEntry = $this->getDatabase()->stock()->where('id', $args['entryId'])->fetch();
|
||||
$product = $this->getDatabase()->products()->where('id', $stockEntry->product_id)->fetch();
|
||||
|
||||
$webhookData = array_merge([
|
||||
$webhookData = [
|
||||
'product' => $product->name,
|
||||
'grocycode' => (string)(new Grocycode(Grocycode::PRODUCT, $stockEntry->product_id, [$stockEntry->stock_id])),
|
||||
], GROCY_LABEL_PRINTER_PARAMS);
|
||||
];
|
||||
|
||||
if (GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING)
|
||||
{
|
||||
$webhookData['due_date'] = $this->getLocalizationService()->__t('DD') . ': ' . $stockEntry->best_before_date;
|
||||
}
|
||||
|
||||
if (GROCY_LABEL_PRINTER_RUN_SERVER)
|
||||
{
|
||||
(new WebhookRunner())->run(GROCY_LABEL_PRINTER_WEBHOOK, $webhookData, GROCY_LABEL_PRINTER_HOOK_JSON);
|
||||
}
|
||||
$this->getWebhookService()->run(WebhookService::EVENT_STOCK_ENTRY_PRINT_LABEL, $webhookData);
|
||||
|
||||
return $this->ApiResponse($response, $webhookData);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Grocy\Helpers;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\ExceptionRequestException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class WebhookRunner
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->client = new Client(['timeout' => 2.0]);
|
||||
}
|
||||
|
||||
private $client;
|
||||
|
||||
public function run($url, $args, $json = false)
|
||||
{
|
||||
$reqArgs = [];
|
||||
if ($json)
|
||||
{
|
||||
$reqArgs = ['json' => $args];
|
||||
}
|
||||
else
|
||||
{
|
||||
$reqArgs = ['form_params' => $args];
|
||||
}
|
||||
try
|
||||
{
|
||||
file_put_contents('php://stderr', 'Running Webhook: ' . $url . "\n" . print_r($reqArgs, true));
|
||||
|
||||
$this->client->request('POST', $url, $reqArgs);
|
||||
}
|
||||
catch (RequestException $e)
|
||||
{
|
||||
file_put_contents('php://stderr', 'Webhook failed: ' . $url . "\n" . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function runAll($urls, $args)
|
||||
{
|
||||
foreach ($urls as $url)
|
||||
{
|
||||
$this->run($url, $args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -76,4 +76,9 @@ class BaseService
|
|||
{
|
||||
return ApplicationService::getInstance();
|
||||
}
|
||||
|
||||
protected function getWebhookService()
|
||||
{
|
||||
return WebhookService::getInstance();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
namespace Grocy\Services;
|
||||
|
||||
use Grocy\Helpers\Grocycode;
|
||||
use Grocy\Helpers\WebhookRunner;
|
||||
use Grocy\Services\WebhookService;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class StockService extends BaseService
|
||||
|
|
@ -220,21 +220,17 @@ class StockService extends BaseService
|
|||
]);
|
||||
$stockRow->save();
|
||||
|
||||
if (GROCY_FEATURE_FLAG_LABEL_PRINTER && GROCY_LABEL_PRINTER_RUN_SERVER)
|
||||
$webhookData = [
|
||||
'product' => $productDetails->product->name,
|
||||
'grocycode' => (string)(new Grocycode(Grocycode::PRODUCT, $productId, [$stockId])),
|
||||
];
|
||||
|
||||
if (GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING)
|
||||
{
|
||||
$webhookData = array_merge([
|
||||
'product' => $productDetails->product->name,
|
||||
'grocycode' => (string)(new Grocycode(Grocycode::PRODUCT, $productId, [$stockId])),
|
||||
], GROCY_LABEL_PRINTER_PARAMS);
|
||||
|
||||
if (GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING)
|
||||
{
|
||||
$webhookData['due_date'] = $this->getLocalizationService()->__t('DD') . ': ' . $bestBeforeDate;
|
||||
}
|
||||
|
||||
$runner = new WebhookRunner();
|
||||
$runner->run(GROCY_LABEL_PRINTER_WEBHOOK, $webhookData, GROCY_LABEL_PRINTER_HOOK_JSON);
|
||||
$webhookData['due_date'] = $this->getLocalizationService()->__t('DD') . ': ' . $bestBeforeDate;
|
||||
}
|
||||
|
||||
$this->getWebhookService()->run(WebhookService::EVENT_ADD_PRODUCT, $webhookData);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -271,20 +267,19 @@ class StockService extends BaseService
|
|||
]);
|
||||
$stockRow->save();
|
||||
|
||||
if ($stockLabelType == 1 && GROCY_FEATURE_FLAG_LABEL_PRINTER && GROCY_LABEL_PRINTER_RUN_SERVER)
|
||||
if ($stockLabelType == 1)
|
||||
{
|
||||
$webhookData = array_merge([
|
||||
$webhookData = [
|
||||
'product' => $productDetails->product->name,
|
||||
'grocycode' => (string)(new Grocycode(Grocycode::PRODUCT, $productId, [$stockId])),
|
||||
], GROCY_LABEL_PRINTER_PARAMS);
|
||||
];
|
||||
|
||||
if (GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING)
|
||||
{
|
||||
$webhookData['due_date'] = $this->getLocalizationService()->__t('DD') . ': ' . $bestBeforeDate;
|
||||
}
|
||||
|
||||
$runner = new WebhookRunner();
|
||||
$runner->run(GROCY_LABEL_PRINTER_WEBHOOK, $webhookData, GROCY_LABEL_PRINTER_HOOK_JSON);
|
||||
$this->getWebhookService()->run(WebhookService::EVENT_ADD_PRODUCT, $webhookData);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -996,20 +991,19 @@ class StockService extends BaseService
|
|||
$newBestBeforeDate = $stockEntry->best_before_date;
|
||||
}
|
||||
|
||||
if (GROCY_FEATURE_FLAG_LABEL_PRINTER && GROCY_LABEL_PRINTER_RUN_SERVER && $productDetails->product->auto_reprint_stock_label == 1 && $newBestBeforeDate != $stockEntry->best_before_date)
|
||||
if ($productDetails->product->auto_reprint_stock_label == 1 && $newBestBeforeDate != $stockEntry->best_before_date)
|
||||
{
|
||||
$webhookData = array_merge([
|
||||
$webhookData = [
|
||||
'product' => $productDetails->product->name,
|
||||
'grocycode' => (string)(new Grocycode(Grocycode::PRODUCT, $productId, [$stockEntry->stock_id])),
|
||||
], GROCY_LABEL_PRINTER_PARAMS);
|
||||
];
|
||||
|
||||
if (GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING)
|
||||
{
|
||||
$webhookData['due_date'] = $this->getLocalizationService()->__t('DD') . ': ' . $newBestBeforeDate;
|
||||
}
|
||||
|
||||
$runner = new WebhookRunner();
|
||||
$runner->run(GROCY_LABEL_PRINTER_WEBHOOK, $webhookData, GROCY_LABEL_PRINTER_HOOK_JSON);
|
||||
$this->getWebhookService()->run(WebhookService::EVENT_OPEN_PRODUCT, $webhookData);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1308,20 +1302,19 @@ class StockService extends BaseService
|
|||
$newBestBeforeDate = date('Y-m-d', strtotime('+' . $productDetails->product->default_best_before_days_after_thawing . ' days'));
|
||||
}
|
||||
|
||||
if (GROCY_FEATURE_FLAG_LABEL_PRINTER && GROCY_LABEL_PRINTER_RUN_SERVER && $productDetails->product->auto_reprint_stock_label == 1 && $stockEntry->best_before_date != $newBestBeforeDate)
|
||||
if ($productDetails->product->auto_reprint_stock_label == 1 && $stockEntry->best_before_date != $newBestBeforeDate)
|
||||
{
|
||||
$webhookData = array_merge([
|
||||
$webhookData = [
|
||||
'product' => $productDetails->product->name,
|
||||
'grocycode' => (string)(new Grocycode(Grocycode::PRODUCT, $productId, [$stockEntry->stock_id])),
|
||||
], GROCY_LABEL_PRINTER_PARAMS);
|
||||
];
|
||||
|
||||
if (GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING)
|
||||
{
|
||||
$webhookData['due_date'] = $this->getLocalizationService()->__t('DD') . ': ' . $newBestBeforeDate;
|
||||
}
|
||||
|
||||
$runner = new WebhookRunner();
|
||||
$runner->run(GROCY_LABEL_PRINTER_WEBHOOK, $webhookData, GROCY_LABEL_PRINTER_HOOK_JSON);
|
||||
$this->getWebhookService()->run(WebhookService::EVENT_TRANSFER_PRODUCT, $webhookData);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
113
services/WebhookService.php
Normal file
113
services/WebhookService.php
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
namespace Grocy\Services;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
|
||||
// Get these from a database table later
|
||||
const WEBHOOKS = [
|
||||
[
|
||||
'url' => GROCY_LABEL_PRINTER_WEBHOOK,
|
||||
'default_args' => GROCY_LABEL_PRINTER_PARAMS,
|
||||
'json' => GROCY_LABEL_PRINTER_HOOK_JSON,
|
||||
'include_events' => [
|
||||
WebhookService::EVENT_BATTERY_PRINT_LABEL,
|
||||
WebhookService::EVENT_CHORE_PRINT_LABEL,
|
||||
WebhookService::EVENT_RECIPE_PRINT_LABEL,
|
||||
WebhookService::EVENT_PRODUCT_PRINT_LABEL,
|
||||
WebhookService::EVENT_STOCK_ENTRY_PRINT_LABEL,
|
||||
WebhookService::EVENT_ADD_PRODUCT,
|
||||
WebhookService::EVENT_OPEN_PRODUCT,
|
||||
WebhookService::EVENT_TRANSFER_PRODUCT,
|
||||
],
|
||||
'exclude_events' => [],
|
||||
'enabled' => GROCY_FEATURE_FLAG_LABEL_PRINTER && GROCY_LABEL_PRINTER_RUN_SERVER,
|
||||
],
|
||||
];
|
||||
|
||||
class WebhookService extends BaseService
|
||||
{
|
||||
const EVENT_BATTERY_PRINT_LABEL = 'battery_print_label';
|
||||
const EVENT_CHORE_PRINT_LABEL = 'chore_print_label';
|
||||
const EVENT_RECIPE_PRINT_LABEL = 'recipe_print_label';
|
||||
const EVENT_PRODUCT_PRINT_LABEL = 'product_print_label';
|
||||
const EVENT_STOCK_ENTRY_PRINT_LABEL = 'stock_entry_print_label';
|
||||
const EVENT_ADD_PRODUCT = 'add_product';
|
||||
const EVENT_OPEN_PRODUCT = 'open_product';
|
||||
const EVENT_TRANSFER_PRODUCT = 'transfer_product';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->client = new Client(['timeout' => 2.0]);
|
||||
}
|
||||
|
||||
private $client;
|
||||
|
||||
private function shouldFire($webhook, $event)
|
||||
{
|
||||
if (!$webhook['enabled'])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$includeEvents = $webhook['include_events'] ?? [];
|
||||
$excludeEvents = $webhook['exclude_events'] ?? [];
|
||||
|
||||
// No restrictions
|
||||
if (empty($includeEvents) && empty($excludeEvents))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only include events
|
||||
if (!empty($includeEvents) && in_array($event, $includeEvents))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only exclude events
|
||||
if (!empty($excludeEvents) && !in_array($event, $excludeEvents))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// No events match
|
||||
return false;
|
||||
}
|
||||
|
||||
public function fire($event, $args)
|
||||
{
|
||||
foreach (WEBHOOKS as $webhook)
|
||||
{
|
||||
if ($this->shouldFire($webhook, $event))
|
||||
{
|
||||
$webhookData = array_merge($webhook['default_args'], $args);
|
||||
$this->run($webhook['url'], $webhookData, $webhook['json']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function run($url, $args, $json = false)
|
||||
{
|
||||
$reqArgs = [];
|
||||
if ($json)
|
||||
{
|
||||
$reqArgs = ['json' => $args];
|
||||
}
|
||||
else
|
||||
{
|
||||
$reqArgs = ['form_params' => $args];
|
||||
}
|
||||
try
|
||||
{
|
||||
file_put_contents('php://stderr', 'Running Webhook: ' . $url . "\n" . print_r($reqArgs, true));
|
||||
|
||||
$this->client->request('POST', $url, $reqArgs);
|
||||
}
|
||||
catch (RequestException $e)
|
||||
{
|
||||
file_put_contents('php://stderr', 'Webhook failed: ' . $url . "\n" . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user