Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/install/http_webhooks.outgoing_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ http_webhooks:
outgoing:
secret: ''
url: ''
events: []
14 changes: 14 additions & 0 deletions http_webhooks.module
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
*/

use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\http_webhooks\OutgoingWebhook;

/**
* Implements hook_help().
Expand Down Expand Up @@ -33,3 +35,15 @@ function http_webhooks_theme() {
],
];
}

function http_webhooks_entity_update(EntityInterface $entity) {
\Drupal::service('http_webhooks.outgoing_webhook')->handle_event($entity, OutgoingWebhook::EVENT_UPDATE);
}

function http_webhooks_entity_create(EntityInterface $entity) {
\Drupal::service('http_webhooks.outgoing_webhook')->handle_event($entity, OutgoingWebhook::EVENT_CREATE);
}

function http_webhooks_entity_delete(EntityInterface $entity) {
\Drupal::service('http_webhooks.outgoing_webhook')->handle_event($entity, OutgoingWebhook::EVENT_DELETE);
}
2 changes: 1 addition & 1 deletion http_webhooks.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ services:
arguments: ['http_webhooks']
http_webhooks.outgoing_webhook:
class: Drupal\http_webhooks\OutgoingWebhook
arguments: ['@http_client', '@serialization.json']
arguments: ['@http_client', '@serialization.json', '@config.factory']
46 changes: 41 additions & 5 deletions src/Form/OutgoingWebhookConfigForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\http_webhooks\OutgoingWebhook;

/**
* Class OutgoingWebhookConfigForm.
Expand All @@ -26,11 +27,21 @@ public function getFormId() {
return 'outgoing_webhook_config_form';
}

protected function getEventOptions() {
return OutgoingWebhook::VALID_EVENTS;
}

/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('http_webhooks.outgoing_config');
$form['url'] = [
'#type' => 'url',
'#title' => $this->t('URL of the webhook'),
'#description' => $this->t('The URL to make the POST request'),
'#default_value' => $config->get('http_webhooks.outgoing.url'),
];
$form['secret'] = [
'#type' => 'password',
'#title' => $this->t('Secret'),
Expand All @@ -39,24 +50,49 @@ public function buildForm(array $form, FormStateInterface $form_state) {
'#size' => 64,
'#default_value' => $config->get('http_webhooks.outgoing.secret'),
];
$form['url'] = [
'#type' => 'url',
'#title' => $this->t('URL of the webhook'),
'#description' => $this->t('The URL to make the POST request'),
'#default_value' => $config->get('http_webhooks.outgoing.url'),
$form['events'] = [
'#type' => 'tableselect',
'#header' => array('type' => 'Entity Type' , 'event' => 'Event'),
'#description' => $this->t("The events that will trigger this webhook."),
'#options' => $this->getEventOptions(),
];
$form['events']['#default_value'] = ($config->isNew()
? []
: $this->deSerializeEvents($config->get('http_webhooks.outgoing.events'))
);
return parent::buildForm($form, $form_state);
}

protected function serializeEvents($events) {
return array_filter(array_values($events));
}

protected function deSerializeEvents($events) {
$options = $this->getEventOptions();
$result = \array_reduce(array_keys($options), function($carry, $key) use($events) {
if (in_array($key, $events)) {
$carry[$key] = $key;
} else {
$carry[$key] = 0;
}
return $carry;
}, []);
$result = (object) $result;
return $result;
}

/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
parent::submitForm($form, $form_state);

$serializedEvents = $this->serializeEvents($form_state->getValue('events'));

$this->config('http_webhooks.outgoing_config')
->set('http_webhooks.outgoing.secret', $form_state->getValue('secret'))
->set('http_webhooks.outgoing.url', $form_state->getValue('url'))
->set('http_webhooks.outgoing.events', $serializedEvents)
->save();
}

Expand Down
67 changes: 65 additions & 2 deletions src/OutgoingWebhook.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,34 @@
<?php

namespace Drupal\http_webhooks;
use GuzzleHttp\ClientInterface;

use Drupal\Component\Serialization\SerializationInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityInterface;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7;
use GuzzleHttp\Psr7\Request;

/**
* Class OutgoingWebhook.
*/
class OutgoingWebhook {
const EVENT_CREATE = "create";
const EVENT_UPDATE = "update";
const EVENT_DELETE = "delete";

const VALID_EVENTS = [
'entity:user:create' => ['type' => 'user' , 'event' => 'create'],
'entity:user:update' => ['type' => 'user' , 'event' => 'update'],
'entity:user:delete' => ['type' => 'user' , 'event' => 'delete'],
'entity:node:create' => ['type' => 'node' , 'event' => 'create'],
'entity:node:update' => ['type' => 'node' , 'event' => 'update'],
'entity:node:delete' => ['type' => 'node' , 'event' => 'delete'],
'entity:comment:create' => ['type' => 'node' , 'event' => 'create'],
'entity:node:update' => ['type' => 'node' , 'event' => 'update'],
'entity:node:delete' => ['type' => 'node' , 'event' => 'delete'],
];

/**
* GuzzleHttp\ClientInterface definition.
Expand All @@ -23,12 +44,54 @@ class OutgoingWebhook {
*/
protected $serializationJson;

/**
* @var \Drupal\Core\Config\ImmutableConfig
*/
protected $config;

/**
* Constructs a new OutgoingWebhook object.
*/
public function __construct(ClientInterface $http_client, SerializationInterface $serialization_json) {
public function __construct(
ClientInterface $http_client,
SerializationInterface $serialization_json,
ConfigFactoryInterface $config_factory
) {
$this->httpClient = $http_client;
$this->serializationJson = $serialization_json;
$this->config = $config_factory->get('http_webhooks.outgoing_config');
}

public function handle_event(EntityInterface $entity, $event) {
$type = $entity->getEntityTypeId();
$eventString = "entity:$type:$event";
$allowed_events = $this->config->get("http_webhooks.outgoing.events");

// only post for entities and events allowed in the configuration
if (in_array($eventString, $allowed_events)) {
$this->post();
};
}

public function post() {
$secret = $this->config->get('http_webhooks.outgoing.secret');
$url = $this->config->get('http_webhooks.outgoing.url');
if (empty($secret) || empty($url)) {
// TODO: log a error message: these configuration are necessary,
return;
}

try {
$response = $this->httpClient->request('POST', $url, [
'json' => ['secret'=> $secret]
]);
} catch(RequestException $e) {
// TODO: log a error message: the request failed
return;
}
$body = $response->getBody();
// TODO: log a success message with the response payload

}

}