Skip to content

Commit f756d06

Browse files
committed
Exclusive filters
1 parent 58fff1b commit f756d06

File tree

8 files changed

+155
-24
lines changed

8 files changed

+155
-24
lines changed

CHANGELOG.md

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

3+
## Unreleased
4+
5+
### Added
6+
- Some webhook filters now disable other mutually-exclusive filters when active and enabled.
7+
- Added `craft\webhooks\filters\ExclusiveFilterInterface`.
8+
39
## 2.3.3 - 2021-04-01
410

511
### Fixed

src/assets/edit/dist/js/EditWebhook.js

Lines changed: 98 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
$noFiltersMessage: null,
1111
$filtersTable: null,
1212
filters: null,
13+
matchingFilters: null,
1314

1415
classVal: null,
1516
eventVal: null,
@@ -24,12 +25,19 @@
2425
this.$filtersTable = $('#filters');
2526

2627
this.filters = {};
28+
this.matchingFilters = [];
29+
2730
const $filterRows = this.$filtersTable.find('tr');
2831
for (let i = 0; i < $filterRows.length; i++) {
29-
const filter = new EditWebhook.Filter($filterRows.eq(i));
32+
const filter = new EditWebhook.Filter(this, $filterRows.eq(i));
3033
this.filters[filter.class] = filter;
34+
if (!filter.$tr.hasClass('hidden')) {
35+
this.matchingFilters.push(filter);
36+
}
3137
}
3238

39+
this.applyExclusions();
40+
3341
this.addListener(this.$nameInput, 'change, keyup', 'handleTextChange');
3442
this.addListener(this.$classInput, 'change, keyup, blur', 'handleEventChange');
3543
this.addListener(this.$eventInput, 'change, keyup, blur', 'handleEventChange');
@@ -74,8 +82,12 @@
7482
this.$noFiltersMessage.addClass('hidden');
7583
this.$filtersTable.removeClass('hidden');
7684
for (let i = 0; i < response.data.filters.length; i++) {
77-
this.filters[response.data.filters[i]].$tr.removeClass('hidden');
85+
const filter = this.filters[response.data.filters[i]];
86+
this.matchingFilters.push(filter);
87+
filter.enable();
88+
filter.$tr.removeClass('hidden');
7889
}
90+
this.applyExclusions();
7991
} else {
8092
this.$noFiltersMessage.removeClass('hidden');
8193
this.$filtersTable.addClass('hidden');
@@ -86,31 +98,50 @@
8698
},
8799

88100
resetFilters: function() {
101+
this.matchingFilters = [];
89102
for (let filter in this.filters) {
90103
if (!this.filters.hasOwnProperty(filter)) {
91104
continue;
92105
}
93106
this.filters[filter].$tr.addClass('hidden');
94-
this.filters[filter].selectIgnore();
107+
this.filters[filter].selectIgnore(false);
95108
}
96-
}
109+
},
110+
111+
applyExclusions: function() {
112+
this.matchingFilters.forEach(f => {
113+
f.enable();
114+
});
115+
this.matchingFilters
116+
.filter(f => f.value === true)
117+
.forEach(f => {
118+
f.excludes.forEach(e => {
119+
this.filters[e].disable();
120+
})
121+
});
122+
},
97123
})
98124

99125
EditWebhook.Filter = Garnish.Base.extend({
126+
manager: null,
100127
$tr: null,
101128
$input: null,
102129
'class': null,
130+
$btnGroup: null,
103131
$noBtn: null,
104132
$ignoreBtn: null,
105133
$yesBtn: null,
106134
value: null,
135+
enabled: false,
107136

108-
init: function($tr) {
137+
init: function(manager, $tr) {
138+
this.manager = manager;
109139
this.$tr = $tr;
110140
this.class = $tr.data('class');
111-
this.$noBtn = $tr.find('.filter-no');
112-
this.$ignoreBtn = $tr.find('.filter-ignore');
113-
this.$yesBtn = $tr.find('.filter-yes');
141+
this.$btnGroup = this.$tr.find('.btngroup');
142+
this.$noBtn = this.$btnGroup.find('.filter-no');
143+
this.$ignoreBtn = this.$btnGroup.find('.filter-ignore');
144+
this.$yesBtn = this.$btnGroup.find('.filter-yes');
114145
this.$input = $tr.find('input');
115146

116147
switch (this.$input.val()) {
@@ -122,30 +153,79 @@
122153
break;
123154
}
124155

125-
this.addListener(this.$noBtn, 'click', 'selectNo');
126-
this.addListener(this.$ignoreBtn, 'click', 'selectIgnore');
127-
this.addListener(this.$yesBtn, 'click', 'selectYes');
128-
this.addListener($tr.find('.btngroup'), 'keydown', 'handleKeydown');
156+
this.enable();
157+
},
158+
159+
/**
160+
* @returns {string[]}
161+
*/
162+
get excludes() {
163+
return this.$tr.data('excludes');
164+
},
165+
166+
enable: function() {
167+
if (!this.enabled) {
168+
this.addListener(this.$btnGroup, 'keydown', 'handleKeydown');
169+
this.addListener(this.$noBtn, 'click', 'selectNo');
170+
this.addListener(this.$ignoreBtn, 'click', 'selectIgnore');
171+
this.addListener(this.$yesBtn, 'click', 'selectYes');
172+
this.$tr.removeClass('disabled');
173+
this.$btnGroup.attr('tabindex', '0');
174+
this.enabled = true;
175+
}
176+
},
177+
178+
disable: function() {
179+
if (this.enabled) {
180+
this.selectIgnore(false);
181+
this.removeAllListeners(this.$btnGroup);
182+
this.removeAllListeners(this.$noBtn);
183+
this.removeAllListeners(this.$ignoreBtn);
184+
this.removeAllListeners(this.$yesBtn);
185+
this.$tr.addClass('disabled');
186+
this.$btnGroup.attr('tabindex', '-1');
187+
this.enabled = false;
188+
}
189+
},
190+
191+
/**
192+
* @param {boolean|null} value
193+
* @param {boolean} [applyExclusions=true]
194+
*/
195+
setValue: function(value, applyExclusions) {
196+
this.value = value;
197+
if (applyExclusions !== false) {
198+
this.manager.applyExclusions();
199+
}
129200
},
130201

131-
selectNo: function() {
202+
/**
203+
* @param {boolean} [applyExclusions=true]
204+
*/
205+
selectNo: function(applyExclusions) {
132206
this.clear();
133207
this.$noBtn.addClass('active');
134-
this.value = false;
208+
this.setValue(false, applyExclusions);
135209
this.$input.val('no');
136210
},
137211

138-
selectIgnore: function() {
212+
/**
213+
* @param {boolean} [applyExclusions=true]
214+
*/
215+
selectIgnore: function(applyExclusions) {
139216
this.clear();
140217
this.$ignoreBtn.addClass('active');
141-
this.value = null;
218+
this.setValue(null, applyExclusions);
142219
this.$input.val('');
143220
},
144221

145-
selectYes: function() {
222+
/**
223+
* @param {boolean} [applyExclusions=true]
224+
*/
225+
selectYes: function(applyExclusions) {
146226
this.clear();
147227
this.$yesBtn.addClass('active');
148-
this.value = true;
228+
this.setValue(true, applyExclusions);
149229
this.$input.val('yes');
150230
},
151231

src/controllers/WebhooksController.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use craft\helpers\ArrayHelper;
77
use craft\helpers\UrlHelper;
88
use craft\webhooks\assets\edit\EditAsset;
9+
use craft\webhooks\filters\ExclusiveFilterInterface;
910
use craft\webhooks\filters\FilterInterface;
1011
use craft\webhooks\Plugin;
1112
use craft\webhooks\Webhook;
@@ -81,17 +82,20 @@ public function actionEdit(int $id = null, int $groupId = null, Webhook $webhook
8182
}
8283

8384
// Filters
84-
$allFilters = [];
85-
foreach (Plugin::getInstance()->getAllFilters() as $class) {
85+
$allFilters = array_map(function(string $class) use ($webhook): array {
8686
/** @var string|FilterInterface $class */
87-
$allFilters[] = [
87+
$config = [
8888
'class' => $class,
8989
'displayName' => $class::displayName(),
9090
'show' => $webhook->class && $webhook->event && $class::show($webhook->class, $webhook->event),
9191
'enabled' => isset($webhook->filters[$class]),
92-
'value' => isset($webhook->filters[$class]) && (bool)$webhook->filters[$class],
92+
'value' => isset($webhook->filters[$class]) && $webhook->filters[$class],
9393
];
94-
}
94+
if (is_subclass_of($class, ExclusiveFilterInterface::class)) {
95+
$config['excludes'] = $class::excludes();
96+
}
97+
return $config;
98+
}, Plugin::getInstance()->getAllFilters());
9599

96100
Craft::$app->getView()->registerAssetBundle(EditAsset::class);
97101

src/filters/BaseElementFilter.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* @author Pixel & Tonic, Inc. <[email protected]>
1717
* @since 2.1.0
1818
*/
19-
abstract class BaseElementFilter extends Component implements FilterInterface
19+
abstract class BaseElementFilter extends Component implements ExclusiveFilterInterface
2020
{
2121
public static function show(string $class, string $event): bool
2222
{
@@ -35,6 +35,11 @@ public static function show(string $class, string $event): bool
3535
));
3636
}
3737

38+
public static function excludes(): array
39+
{
40+
return [];
41+
}
42+
3843
public static function check(Event $event, bool $value): bool
3944
{
4045
if ($event->sender instanceof ElementInterface) {

src/filters/DraftFilter.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ public static function displayName(): string
1919
return Craft::t('webhooks', 'Element is a draft');
2020
}
2121

22+
public static function excludes(): array
23+
{
24+
return [
25+
RevisionFilter::class,
26+
];
27+
}
28+
2229
protected static function checkElement(ElementInterface $element, bool $value): bool
2330
{
2431
$root = ElementHelper::rootElement($element);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace craft\webhooks\filters;
4+
5+
/**
6+
* Exclusive Filter Interface
7+
*
8+
* This can be used by filters which should exclude other filters from being available when this filter is active and enabled.
9+
*
10+
* @author Pixel & Tonic, Inc. <[email protected]>
11+
* @since 2.4.0
12+
*/
13+
interface ExclusiveFilterInterface extends FilterInterface
14+
{
15+
/**
16+
* Returns any filters that should be disabled if this filter is active and enabled.
17+
*
18+
* @return string[]
19+
*/
20+
public static function excludes(): array;
21+
}

src/filters/RevisionFilter.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ public static function displayName(): string
1919
return Craft::t('webhooks', 'Element is a revision');
2020
}
2121

22+
public static function excludes(): array
23+
{
24+
return [
25+
DraftFilter::class,
26+
];
27+
}
28+
2229
protected static function checkElement(ElementInterface $element, bool $value): bool
2330
{
2431
$root = ElementHelper::rootElement($element);

src/templates/_manage/edit.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
class: not filter.show ? 'hidden' : false,
8484
data: {
8585
class: filter.class,
86+
excludes: filter.excludes ?? [],
8687
},
8788
} %}
8889
<th>{{ filter.displayName }}</th>

0 commit comments

Comments
 (0)