diff --git a/extensions/tags/js/admin/dist/extension.js b/extensions/tags/js/admin/dist/extension.js index d08445a7a..dee1b7b5b 100644 --- a/extensions/tags/js/admin/dist/extension.js +++ b/extensions/tags/js/admin/dist/extension.js @@ -1301,6 +1301,7 @@ System.register('flarum/tags/models/Tag', ['flarum/Model', 'flarum/utils/mixin', isRestricted: Model.attribute('isRestricted'), canStartDiscussion: Model.attribute('canStartDiscussion'), + canAddToDiscussion: Model.attribute('canAddToDiscussion'), isPrimary: computed('position', 'parent', function (position, parent) { return position !== null && parent === false; diff --git a/extensions/tags/js/forum/dist/extension.js b/extensions/tags/js/forum/dist/extension.js index 68ad9f0c6..131863585 100644 --- a/extensions/tags/js/forum/dist/extension.js +++ b/extensions/tags/js/forum/dist/extension.js @@ -446,9 +446,19 @@ System.register('flarum/tags/components/TagDiscussionModal', ['flarum/components babelHelpers.get(Object.getPrototypeOf(TagDiscussionModal.prototype), 'init', this).call(this); - this.tags = sortTags(app.store.all('tags').filter(function (tag) { - return tag.canStartDiscussion(); - })); + this.tags = app.store.all('tags'); + + if (this.props.discussion) { + this.tags = this.tags.filter(function (tag) { + return tag.canAddToDiscussion() || _this2.props.discussion.tags().indexOf(tag) !== -1; + }); + } else { + this.tags = this.tags.filter(function (tag) { + return tag.canStartDiscussion(); + }); + } + + this.tags = sortTags(this.tags); this.selected = []; this.filter = m.prop(''); @@ -1258,6 +1268,7 @@ System.register('flarum/tags/models/Tag', ['flarum/Model', 'flarum/utils/mixin', isRestricted: Model.attribute('isRestricted'), canStartDiscussion: Model.attribute('canStartDiscussion'), + canAddToDiscussion: Model.attribute('canAddToDiscussion'), isPrimary: computed('position', 'parent', function (position, parent) { return position !== null && parent === false; diff --git a/extensions/tags/js/forum/src/components/TagDiscussionModal.js b/extensions/tags/js/forum/src/components/TagDiscussionModal.js index 28b7038b3..f81948e8e 100644 --- a/extensions/tags/js/forum/src/components/TagDiscussionModal.js +++ b/extensions/tags/js/forum/src/components/TagDiscussionModal.js @@ -14,7 +14,15 @@ export default class TagDiscussionModal extends Modal { init() { super.init(); - this.tags = sortTags(app.store.all('tags').filter(tag => tag.canStartDiscussion())); + this.tags = app.store.all('tags'); + + if (this.props.discussion) { + this.tags = this.tags.filter(tag => tag.canAddToDiscussion() || this.props.discussion.tags().indexOf(tag) !== -1); + } else { + this.tags = this.tags.filter(tag => tag.canStartDiscussion()); + } + + this.tags = sortTags(this.tags); this.selected = []; this.filter = m.prop(''); diff --git a/extensions/tags/js/lib/models/Tag.js b/extensions/tags/js/lib/models/Tag.js index 04cda1519..b66c1f494 100644 --- a/extensions/tags/js/lib/models/Tag.js +++ b/extensions/tags/js/lib/models/Tag.js @@ -23,6 +23,7 @@ export default class Tag extends mixin(Model, { isRestricted: Model.attribute('isRestricted'), canStartDiscussion: Model.attribute('canStartDiscussion'), + canAddToDiscussion: Model.attribute('canAddToDiscussion'), isPrimary: computed('position', 'parent', (position, parent) => position !== null && parent === false) }) {} diff --git a/extensions/tags/src/Access/TagPolicy.php b/extensions/tags/src/Access/TagPolicy.php index c64ba2a93..49ad05abd 100755 --- a/extensions/tags/src/Access/TagPolicy.php +++ b/extensions/tags/src/Access/TagPolicy.php @@ -43,4 +43,14 @@ class TagPolicy extends AbstractPolicy return true; } } + + /** + * @param User $actor + * @param Tag $tag + * @return bool|null + */ + public function addToDiscussion(User $actor, Tag $tag) + { + return $this->startDiscussion($actor, $tag); + } } diff --git a/extensions/tags/src/Api/Serializer/TagSerializer.php b/extensions/tags/src/Api/Serializer/TagSerializer.php index 256dd4d91..8979456b1 100644 --- a/extensions/tags/src/Api/Serializer/TagSerializer.php +++ b/extensions/tags/src/Api/Serializer/TagSerializer.php @@ -40,7 +40,8 @@ class TagSerializer extends AbstractSerializer 'isChild' => (bool) $tag->parent_id, 'isHidden' => (bool) $tag->is_hidden, 'lastTime' => $this->formatDate($tag->last_time), - 'canStartDiscussion' => $this->actor->can('startDiscussion', $tag) + 'canStartDiscussion' => $this->actor->can('startDiscussion', $tag), + 'canAddToDiscussion' => $this->actor->can('addToDiscussion', $tag) ]; if ($this->actor->isAdmin()) { diff --git a/extensions/tags/src/Listener/SaveTagsToDatabase.php b/extensions/tags/src/Listener/SaveTagsToDatabase.php index 30a4b0b4a..8454a09a6 100755 --- a/extensions/tags/src/Listener/SaveTagsToDatabase.php +++ b/extensions/tags/src/Listener/SaveTagsToDatabase.php @@ -81,12 +81,18 @@ class SaveTagsToDatabase if ($discussion->exists) { $oldTags = $discussion->tags()->get(); - $oldTagIds = $oldTags->lists('id'); + $oldTagIds = $oldTags->lists('id')->all(); if ($oldTagIds == $newTagIds) { return; } + foreach ($newTags as $tag) { + if (! in_array($tag->id, $oldTagIds) && $actor->cannot('addToDiscussion', $tag)) { + throw new PermissionDeniedException; + } + } + $discussion->raise( new DiscussionWasTagged($discussion, $actor, $oldTags->all()) );