<?php
 namespace App\Webhook; class SendRequest { private $entity; private $id; private $action; private $actuallySent = false; public function __construct(string $entity, int $id, string $action) { $this->entity = $entity; $this->id = $id; $this->action = $action; } public function send() { $this->checkInput(); $entityDetails = \App\Webhook\QueueManager::getInstance()->getRecord($this->entity, $this->id, $this->action, true); $entityChanged = new \App\Webhook\EntityChanged($this->entity, $this->id, $this->action, $entityDetails['lastSentValue']); $entityChanged->process(); if ($this->shouldSend($entityDetails, $entityChanged)) { $this->doSend($entityDetails); $this->actuallySent = true; } if ($entityDetails['toSend']) { \App\Webhook\QueueManager::getInstance()->confirmEntityAction($this->entity, $this->id, $this->action, $entityChanged->getNewSendValue()); } } public function wasActuallySent() { return $this->actuallySent; } private function checkInput() { if (!\DB::isInsideTransaction()) { throw new \Exception('You must be inside a transaction when using '.__CLASS__); } $msgs = new \App\MessagesCollector(); if (!$this->entity) { $msgs->addWarning('The `entity` field is not set when sending the webhook.'); } if (!is_numeric($this->id) or !$this->id) { $msgs->addWarning('The `id` field is not set when sending the webhook.'); } if (!$this->action) { $msgs->addWarning('The `action` field is not set when sending the webhook.'); } $webhookCfg = \App\Config\WebhookQueue::getInstance(); if (!$webhookCfg->get('enabled')) { $msgs->addWarning('The `webhook` is disabled.'); } if ($msgs->hasErrorOrWarning()) { throw new \App\MessagesException($msgs); } } private function shouldSend(array $entityDetails, \App\Webhook\EntityChanged $entityChangedObj) { if (!$entityDetails['toSend']) { return false; } $webhookCfg = \App\Config\WebhookQueue::getInstance(); if (!$webhookCfg->getActiveEntityAction($this->entity, $this->action)) { return false; } if (!$entityChangedObj->shouldNotify()) { return false; } return true; } private function doSend() { $postData = [ 'entity' => $this->entity, 'id' => $this->id, 'action' => $this->action, ]; $webhookCfg = \App\Config\WebhookQueue::getInstance(); $msgs = new \App\MessagesCollector(); $ch = curl_init(); if (!$ch) { $msgs->addError( 'Could not send webhook request due to a technical problem. Could not initialize CURL.' ); throw new \App\MessagesException($msgs); } curl_setopt($ch, CURLOPT_URL, $webhookCfg->get('url')); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_USERAGENT, "TINA Webhook"); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); $headers = ['Content-Type: application/x-www-form-urlencoded']; if ($webhookCfg->get('username')) { $headers[] = 'Authorization: Basic '.base64_encode($webhookCfg->get('username').':'.$webhookCfg->get('password')); } curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $response = curl_exec ($ch); if (curl_errno($ch)) { $msgs->addError( sprintf( 'CURL error code and number: %s / %s', curl_errno($ch), curl_error($ch) ) ); throw new \App\MessagesException($msgs); } $curlDetails = curl_getinfo($ch); if ($curlDetails['http_code']!=200) { $msgs->addError( sprintf( 'The received HTTP code is %s instead of 200.', $curlDetails['http_code'] ) ); throw new \App\MessagesException($msgs); } if ($response!='OK') { $msgs->addError( sprintf( 'The request was made, but the response did not indicate a successful execution - it should have been `OK`. Actual response: %s', $response ) ); throw new \App\MessagesException($msgs); } } } 