161 lines
5.8 KiB
PHP
Executable File
161 lines
5.8 KiB
PHP
Executable File
<?php
|
|
|
|
namespace Mautic\WebhookBundle\Helper;
|
|
|
|
use Doctrine\Common\Collections\Collection;
|
|
use GuzzleHttp\Client;
|
|
use Mautic\CoreBundle\Helper\AbstractFormFieldHelper;
|
|
use Mautic\LeadBundle\Entity\Lead;
|
|
use Mautic\LeadBundle\Helper\TokenHelper;
|
|
use Mautic\LeadBundle\Model\CompanyModel;
|
|
use Mautic\WebhookBundle\Event\WebhookRequestEvent;
|
|
use Mautic\WebhookBundle\WebhookEvents;
|
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
|
|
|
class CampaignHelper
|
|
{
|
|
/**
|
|
* Cached contact values in format [contact_id => [key1 => val1, key2 => val1]].
|
|
*/
|
|
private array $contactsValues = [];
|
|
|
|
public function __construct(
|
|
protected Client $client,
|
|
protected CompanyModel $companyModel,
|
|
private EventDispatcherInterface $dispatcher,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Prepares the neccessary data transformations and then makes the HTTP request.
|
|
*/
|
|
public function fireWebhook(array $config, Lead $contact): void
|
|
{
|
|
$payload = $this->getPayload($config, $contact);
|
|
$headers = $this->getHeaders($config, $contact);
|
|
$url = rawurldecode(TokenHelper::findLeadTokens($config['url'], $this->getContactValues($contact), true));
|
|
|
|
$webhookRequestEvent = new WebhookRequestEvent($contact, $url, $headers, $payload);
|
|
$this->dispatcher->dispatch($webhookRequestEvent, WebhookEvents::WEBHOOK_ON_REQUEST);
|
|
|
|
$this->makeRequest(
|
|
$webhookRequestEvent->getUrl(),
|
|
$config['method'],
|
|
$config['timeout'],
|
|
$webhookRequestEvent->getHeaders(),
|
|
$webhookRequestEvent->getPayload()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Gets the payload fields from the config and if there are tokens it translates them to contact values.
|
|
*/
|
|
private function getPayload(array $config, Lead $contact): array
|
|
{
|
|
$payload = !empty($config['additional_data']['list']) ? $config['additional_data']['list'] : '';
|
|
$payload = array_flip(AbstractFormFieldHelper::parseList($payload));
|
|
|
|
return $this->getTokenValues($payload, $contact);
|
|
}
|
|
|
|
/**
|
|
* Gets the payload fields from the config and if there are tokens it translates them to contact values.
|
|
*/
|
|
private function getHeaders(array $config, Lead $contact): array
|
|
{
|
|
$headers = !empty($config['headers']['list']) ? $config['headers']['list'] : '';
|
|
$headers = array_flip(AbstractFormFieldHelper::parseList($headers));
|
|
|
|
return $this->getTokenValues($headers, $contact);
|
|
}
|
|
|
|
/**
|
|
* @param string $url
|
|
* @param string $method
|
|
* @param int $timeout
|
|
*
|
|
* @throws \InvalidArgumentException
|
|
* @throws \OutOfRangeException
|
|
*/
|
|
private function makeRequest($url, $method, $timeout, array $headers, array $payload): void
|
|
{
|
|
switch ($method) {
|
|
case 'get':
|
|
$payload = $url.(parse_url($url, PHP_URL_QUERY) ? '&' : '?').http_build_query($payload);
|
|
$response = $this->client->get($payload, [
|
|
\GuzzleHttp\RequestOptions::HEADERS => $headers,
|
|
\GuzzleHttp\RequestOptions::TIMEOUT => $timeout,
|
|
]);
|
|
break;
|
|
case 'post':
|
|
case 'put':
|
|
case 'patch':
|
|
$headers = array_change_key_case($headers);
|
|
$options = [
|
|
\GuzzleHttp\RequestOptions::HEADERS => $headers,
|
|
\GuzzleHttp\RequestOptions::TIMEOUT => $timeout,
|
|
];
|
|
if (array_key_exists('content-type', $headers) && 'application/json' == strtolower($headers['content-type'])) {
|
|
$options[\GuzzleHttp\RequestOptions::BODY] = json_encode($payload);
|
|
} else {
|
|
$options[\GuzzleHttp\RequestOptions::FORM_PARAMS] = $payload;
|
|
}
|
|
$response = $this->client->request($method, $url, $options);
|
|
break;
|
|
case 'delete':
|
|
$response = $this->client->delete($url, [
|
|
\GuzzleHttp\RequestOptions::HEADERS => $headers,
|
|
\GuzzleHttp\RequestOptions::TIMEOUT => $timeout,
|
|
]);
|
|
break;
|
|
default:
|
|
throw new \InvalidArgumentException('HTTP method "'.$method.' is not supported."');
|
|
}
|
|
|
|
if (!in_array($response->getStatusCode(), [200, 201])) {
|
|
throw new \OutOfRangeException('Campaign webhook response returned error code: '.$response->getStatusCode());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Translates tokens to values.
|
|
*/
|
|
private function getTokenValues(array $rawTokens, Lead $contact): array
|
|
{
|
|
$values = [];
|
|
$contactValues = $this->getContactValues($contact);
|
|
|
|
foreach ($rawTokens as $key => $value) {
|
|
$values[$key] = rawurldecode(TokenHelper::findLeadTokens($value, $contactValues, true));
|
|
}
|
|
|
|
return $values;
|
|
}
|
|
|
|
/**
|
|
* Gets array of contact values.
|
|
*
|
|
* @return array
|
|
*/
|
|
private function getContactValues(Lead $contact)
|
|
{
|
|
if (empty($this->contactsValues[$contact->getId()])) {
|
|
$this->contactsValues[$contact->getId()] = $contact->getProfileFields();
|
|
$this->contactsValues[$contact->getId()]['ipAddress'] = $this->ipAddressesToCsv($contact->getIpAddresses());
|
|
$this->contactsValues[$contact->getId()]['companies'] = $this->companyModel->getRepository()->getCompaniesByLeadId($contact->getId());
|
|
}
|
|
|
|
return $this->contactsValues[$contact->getId()];
|
|
}
|
|
|
|
private function ipAddressesToCsv(Collection $ipAddresses): string
|
|
{
|
|
$addresses = [];
|
|
foreach ($ipAddresses as $ipAddress) {
|
|
$addresses[] = $ipAddress->getIpAddress();
|
|
}
|
|
|
|
return implode(',', $addresses);
|
|
}
|
|
}
|