Skip to content

Commit 9295f7c

Browse files
committed
Merge branch 'release/2.1.0'
2 parents b9a79d9 + 1ed28b8 commit 9295f7c

24 files changed

+686
-5
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Release Notes for Webhooks for Craft CMS
22

3+
## 2.1.0 - 2019-07-26
4+
5+
### Added
6+
- Webhooks for element events can now be executed depending on whether the element is new, is a draft/revision, or is being duplicated/propagated/bulk-resaved. ([#14](https://github.com/craftcms/webhooks/issues/14))
7+
- Modules and plugins can register additional webhook filters using the new `craft\webhooks\Plugin::EVENT_REGISTER_FILTER_TYPES` event.
8+
9+
### Fixed
10+
- Fixed an error that could occur when detecting available component classes in Craft 3.2.
11+
312
## 2.0.1 - 2019-03-20
413

514
### Fixed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "craftcms/webhooks",
33
"description": "Post webhooks when events are triggered in Craft CMS.",
4-
"version": "2.0.1",
4+
"version": "2.1.0",
55
"type": "craft-plugin",
66
"keywords": [
77
"html",

src/Plugin.php

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,20 @@
44

55
use Craft;
66
use craft\db\Query;
7+
use craft\events\RegisterComponentTypesEvent;
78
use craft\events\RegisterUrlRulesEvent;
89
use craft\helpers\ArrayHelper;
910
use craft\helpers\Db;
1011
use craft\helpers\Json;
1112
use craft\helpers\StringHelper;
1213
use craft\web\UrlManager;
14+
use craft\webhooks\filters\DraftFilter;
15+
use craft\webhooks\filters\DuplicatingFilter;
16+
use craft\webhooks\filters\FilterInterface;
17+
use craft\webhooks\filters\NewElementFilter;
18+
use craft\webhooks\filters\PropagatingFilter;
19+
use craft\webhooks\filters\ResavingFilter;
20+
use craft\webhooks\filters\RevisionFilter;
1321
use GuzzleHttp\Exception\RequestException;
1422
use GuzzleHttp\RequestOptions;
1523
use yii\base\Arrayable;
@@ -37,6 +45,29 @@ class Plugin extends \craft\base\Plugin
3745
const STATUS_REQUESTED = 'requested';
3846
const STATUS_DONE = 'done';
3947

48+
/**
49+
* @event RegisterComponentTypesEvent The event that is triggered when registering filter types.
50+
*
51+
* Filter types must implement [[FilterInterface]].
52+
* ---
53+
* ```php
54+
* use craft\events\RegisterComponentTypesEvent;
55+
* use craft\webhooks\Plugin as Webhooks;
56+
* use yii\base\Event;
57+
*
58+
* if (class_exists(Webhooks::class)) {
59+
* Event::on(Webhooks::class,
60+
* Webhooks::EVENT_REGISTER_FILTER_TYPES,
61+
* function(RegisterComponentTypesEvent $event) {
62+
* $event->types[] = MyFilterType::class;
63+
* }
64+
* );
65+
* }
66+
* ```
67+
* @since 2.1
68+
*/
69+
const EVENT_REGISTER_FILTER_TYPES = 'registerFilterTypes';
70+
4071
// Properties
4172
// =========================================================================
4273

@@ -48,7 +79,7 @@ class Plugin extends \craft\base\Plugin
4879
/**
4980
* @inheritdoc
5081
*/
51-
public $schemaVersion = '2.0.1';
82+
public $schemaVersion = '2.1.0';
5283

5384
// Public Methods
5485
// =========================================================================
@@ -79,6 +110,14 @@ public function init()
79110

80111
foreach ($webhooks as $webhook) {
81112
Event::on($webhook->class, $webhook->event, function(Event $e) use ($webhook) {
113+
// Make sure it passes the filters
114+
foreach ($webhook->filters as $filterClass => $filterValue) {
115+
/** @var string|FilterInterface $filterClass */
116+
if (class_exists($filterClass) && !$filterClass::check($e, $filterValue)) {
117+
return;
118+
}
119+
}
120+
82121
if ($webhook->method === 'post') {
83122
// Build out the body data
84123
if ($webhook->payloadTemplate) {
@@ -329,4 +368,28 @@ protected function createSettingsModel()
329368
{
330369
return new Settings();
331370
}
371+
372+
/**
373+
* Returns all available filter classes.
374+
*
375+
* @return string[] The available field type classes
376+
*/
377+
public function getAllFilters(): array
378+
{
379+
$filterTypes = [
380+
NewElementFilter::class,
381+
DraftFilter::class,
382+
RevisionFilter::class,
383+
DuplicatingFilter::class,
384+
PropagatingFilter::class,
385+
ResavingFilter::class,
386+
];
387+
388+
$event = new RegisterComponentTypesEvent([
389+
'types' => $filterTypes
390+
]);
391+
$this->trigger(self::EVENT_REGISTER_FILTER_TYPES, $event);
392+
393+
return $event->types;
394+
}
332395
}

src/Webhook.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ class Webhook extends Model
4747
*/
4848
public $event;
4949

50+
/**
51+
* @var array
52+
*/
53+
public $filters = [];
54+
5055
/**
5156
* @var string
5257
*/
@@ -142,6 +147,21 @@ function(string $attribute, array $params = null, Validator $validator) {
142147
}
143148
}
144149
],
150+
[
151+
['filters'],
152+
function(string $attribute) {
153+
foreach ($this->filters as $class => &$value) {
154+
if ($value === 'yes') {
155+
$value = true;
156+
} else if ($value === 'no') {
157+
$value = false;
158+
}
159+
if (!is_bool($value)) {
160+
unset($this->filters[$class]);
161+
}
162+
}
163+
}
164+
],
145165
[['userAttributes', 'senderAttributes'], 'validateAttributeList'],
146166
[['eventAttributes'], 'validateAttributeList', 'params' => ['regex' => '/^[a-z]\w*\.[a-z]\w*(?:\.[a-z]\w*)*$/i']],
147167
[['payloadTemplate'], 'validatePayloadTemplate'],

src/WebhookHelper.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ private static function _findClasses(): array
109109
!class_exists($class, false) &&
110110
!interface_exists($class, false) &&
111111
!trait_exists($class, false) &&
112+
strpos($class, 'craft\\test\\') !== 0 &&
112113
file_exists($file) &&
113114
substr($class, -4) !== 'Test' &&
114115
substr($class, -8) !== 'TestCase'

src/WebhookManager.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Craft;
66
use craft\db\Query;
7+
use craft\helpers\Json;
78
use craft\helpers\StringHelper;
89
use yii\base\InvalidArgumentException;
910

@@ -196,6 +197,7 @@ public function saveWebhook(Webhook $webhook, bool $runValidation = true): bool
196197
'name' => $name,
197198
'class' => $webhook->class,
198199
'event' => $webhook->event,
200+
'filters' => Json::encode($webhook->filters),
199201
'method' => $webhook->method,
200202
'url' => $webhook->url,
201203
'userAttributes' => $webhook->userAttributes,
@@ -236,7 +238,7 @@ public function deleteWebhookById(int $id)
236238
private function _createWebhookQuery(): Query
237239
{
238240
return (new Query())
239-
->select(['id', 'groupId', 'enabled', 'name', 'class', 'event', 'method', 'url', 'userAttributes', 'senderAttributes', 'eventAttributes', 'payloadTemplate'])
241+
->select(['id', 'groupId', 'enabled', 'name', 'class', 'event', 'filters', 'method', 'url', 'userAttributes', 'senderAttributes', 'eventAttributes', 'payloadTemplate'])
240242
->from(['{{%webhooks}}']);
241243
}
242244

@@ -251,6 +253,12 @@ private function _createWebhook(array $result, bool $isMysql = null): Webhook
251253
$result['name'] = html_entity_decode($result['name'], ENT_QUOTES | ENT_HTML5);
252254
}
253255

256+
if ($result['filters']) {
257+
$result['filters'] = Json::decode($result['filters']);
258+
} else {
259+
$result['filters'] = [];
260+
}
261+
254262
return new Webhook($result);
255263
}
256264

src/assets/edit/EditAsset.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,8 @@ class EditAsset extends AssetBundle
2727
public $js = [
2828
'js/EditWebhook.js',
2929
];
30+
31+
public $css = [
32+
'css/edit-webhook.css',
33+
];
3034
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#filter-pane,
2+
#filter-pane p {
3+
display: inline-block;
4+
}
5+
6+
#no-filters {
7+
margin: 0;
8+
}
9+
10+
#filters tr:first-child > * {
11+
border-top: none;
12+
padding-top: 0;
13+
}
14+
15+
#filters tr:last-child > * {
16+
border-bottom: none;
17+
padding-bottom: 0;
18+
}
19+
20+
#filters th {
21+
font-weight: normal;
22+
}
23+
24+
#filters .btngroup:focus {
25+
outline: none;
26+
}
27+
28+
#filters .btn[data-icon]:before {
29+
margin-top: -2px;
30+
width: 1em;
31+
}
32+
33+
#filters .filter-yes {
34+
color: #27AE60;
35+
}
36+
37+
#filters .filter-no {
38+
color: #D0021B;
39+
}
40+
41+
#filters .filter-ignore .status {
42+
margin: 0;
43+
}

0 commit comments

Comments
 (0)