mirror of
https://github.com/flarum/core.git
synced 2025-08-06 16:36:47 +02:00
Merge remote-tracking branch 'extensions_subscriptions/REWRITE'
This commit is contained in:
19
extensions/subscriptions/.editorconfig
Normal file
19
extensions/subscriptions/.editorconfig
Normal file
@@ -0,0 +1,19 @@
|
||||
# EditorConfig helps developers define and maintain consistent
|
||||
# coding styles between different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.{diff,md}]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{php,xml,json}]
|
||||
indent_size = 4
|
18
extensions/subscriptions/.gitattributes
vendored
Normal file
18
extensions/subscriptions/.gitattributes
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
.gitattributes export-ignore
|
||||
.gitignore export-ignore
|
||||
.gitmodules export-ignore
|
||||
.github export-ignore
|
||||
.travis export-ignore
|
||||
.travis.yml export-ignore
|
||||
.editorconfig export-ignore
|
||||
.styleci.yml export-ignore
|
||||
|
||||
phpunit.xml export-ignore
|
||||
tests export-ignore
|
||||
|
||||
js/dist/* -diff
|
||||
js/dist/* linguist-generated
|
||||
js/dist-typings/* linguist-generated
|
||||
js/yarn.lock -diff
|
||||
|
||||
* text=auto eol=lf
|
15
extensions/subscriptions/.github/workflows/backend.yml
vendored
Normal file
15
extensions/subscriptions/.github/workflows/backend.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
name: Subscriptions PHP
|
||||
|
||||
on: [workflow_dispatch, push, pull_request]
|
||||
|
||||
# The reusable workflow definitions will be moved to the `flarum/framework` repo soon.
|
||||
# This will break your current script.
|
||||
# When this happens, run `flarum-cli audit infra --fix` to update your infrastructure.
|
||||
|
||||
jobs:
|
||||
run:
|
||||
uses: flarum/.github/.github/workflows/REUSABLE_backend.yml@main
|
||||
with:
|
||||
enable_backend_testing: false
|
||||
|
||||
backend_directory: .
|
21
extensions/subscriptions/.github/workflows/frontend.yml
vendored
Normal file
21
extensions/subscriptions/.github/workflows/frontend.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
name: Subscriptions JS
|
||||
|
||||
on: [workflow_dispatch, push, pull_request]
|
||||
|
||||
# The reusable workflow definitions will be moved to the `flarum/framework` repo soon.
|
||||
# This will break your current script.
|
||||
# When this happens, run `flarum-cli audit infra --fix` to update your infrastructure.
|
||||
|
||||
jobs:
|
||||
run:
|
||||
uses: flarum/.github/.github/workflows/REUSABLE_frontend.yml@main
|
||||
with:
|
||||
enable_bundlewatch: false
|
||||
enable_prettier: true
|
||||
enable_typescript: false
|
||||
|
||||
frontend_directory: ./js
|
||||
main_git_branch: master
|
||||
|
||||
secrets:
|
||||
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}
|
12
extensions/subscriptions/.gitignore
vendored
Normal file
12
extensions/subscriptions/.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
/vendor
|
||||
composer.lock
|
||||
composer.phar
|
||||
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
tests/.phpunit.result.cache
|
||||
/tests/integration/tmp
|
||||
.vagrant
|
||||
.idea/*
|
||||
.vscode
|
||||
js/coverage-ts
|
14
extensions/subscriptions/.styleci.yml
Normal file
14
extensions/subscriptions/.styleci.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
preset: recommended
|
||||
|
||||
enabled:
|
||||
- logical_not_operators_with_successor_space
|
||||
|
||||
disabled:
|
||||
- align_double_arrow
|
||||
- blank_line_after_opening_tag
|
||||
- multiline_array_trailing_comma
|
||||
- new_with_braces
|
||||
- phpdoc_align
|
||||
- phpdoc_order
|
||||
- phpdoc_separation
|
||||
- phpdoc_types
|
73
extensions/subscriptions/CHANGELOG.md
Normal file
73
extensions/subscriptions/CHANGELOG.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Changelog
|
||||
|
||||
## [1.2.0](https://github.com/flarum/subscriptions/compare/v1.1.0...v1.2.0)
|
||||
|
||||
### Changed
|
||||
- Set priority on subscription sidebar item (https://github.com/flarum/subscriptions/pull/43).
|
||||
|
||||
## [1.1.0](https://github.com/flarum/subscriptions/compare/v1.0.0...v1.1.0)
|
||||
|
||||
### Changed
|
||||
- Use css variables for badge (https://github.com/flarum/subscriptions/pulls/42)
|
||||
- Add Prettier config and Update dependencies (https://github.com/flarum/subscriptions/pulls/41)
|
||||
|
||||
## [1.0.0](https://github.com/flarum/subscriptions/compare/v0.1.0-beta.16...v1.0.0)
|
||||
|
||||
### Changed
|
||||
- Compatibility with Flarum v1.0.0.
|
||||
|
||||
### Fixed
|
||||
- Tooltips generate a deprecation warning
|
||||
- Inconsistent data for subscribed provided by API (https://github.com/flarum/subscriptions/pull/37)
|
||||
|
||||
## [0.1.0-beta.16](https://github.com/flarum/subscriptions/compare/v0.1.0-beta.15...v0.1.0-beta.16)
|
||||
|
||||
### Changed
|
||||
- Updated admin category from discussion to feature (https://github.com/flarum/subscriptions/pull/39)
|
||||
- Moved locale files from translation pack to extension (https://github.com/flarum/subscriptions/pull/34)
|
||||
|
||||
### Fixed
|
||||
- User state for discussion list persists across different discussion pages (https://github.com/flarum/subscriptions/pull/38)
|
||||
|
||||
## [0.1.0-beta.15](https://github.com/flarum/subscriptions/compare/v0.1.0-beta.14...v0.1.0-beta.15)
|
||||
|
||||
### Changed
|
||||
- Updated composer.json and admin javascript for new admin area.
|
||||
- Updated to use newest extenders.
|
||||
|
||||
## [0.1.0-beta.14](https://github.com/flarum/subscriptions/compare/v0.1.0-beta.13...v0.1.0-beta.14)
|
||||
|
||||
### Added
|
||||
- Meta title now available for following page (#23)
|
||||
|
||||
### Changed
|
||||
- Updated mithril to version 2
|
||||
- Load language strings correctly on en-/disable
|
||||
- Updated JS dependencies
|
||||
- Notification emails now are translatable (#30)
|
||||
|
||||
### Fixed
|
||||
- Button colors for dark mode were too vague (#26)
|
||||
|
||||
## [0.1.0-beta.13](https://github.com/flarum/subscriptions/compare/v0.1.0-beta.12...v0.1.0-beta.13)
|
||||
|
||||
### Changed
|
||||
- Updated JS dependencies
|
||||
|
||||
### Fixed
|
||||
- Send "new post" email through queue (flarum/core#1869)
|
||||
|
||||
## [0.1.0-beta.12](https://github.com/flarum/subscriptions/compare/v0.1.0-beta.9...v0.1.0-beta.12)
|
||||
|
||||
### Fixed
|
||||
- WhereExists performed extremely bad, impacting the following gambit (#22)
|
||||
|
||||
## [0.1.0-beta.9](https://github.com/flarum/subscriptions/compare/v0.1.0-beta.8...v0.1.0-beta.9)
|
||||
|
||||
### Changed
|
||||
- Replace event subscribers (that resolve services too early) with listeners ([7ac73b8](https://github.com/flarum/subscriptions/commit/7ac73b834023e997147d4dd9c851a2ea73deba4b))
|
||||
|
||||
### Fixed
|
||||
- Post content with code blocks could corrupt notification emails ([16a441c](https://github.com/flarum/subscriptions/commit/16a441c8a85fda824b39acd5ec58a6abe3a8d760))
|
||||
- JS: Vulnerable lodash dependency ([782e31c](https://github.com/flarum/subscriptions/commit/782e31c56a519aa74f80cb8024c7b912a7fdb925))
|
||||
|
22
extensions/subscriptions/LICENSE
Normal file
22
extensions/subscriptions/LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019-2021 Stichting Flarum (Flarum Foundation)
|
||||
Copyright (c) 2014-2019 Toby Zerner (toby.zerner@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
60
extensions/subscriptions/composer.json
Normal file
60
extensions/subscriptions/composer.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "flarum/subscriptions",
|
||||
"description": "Allow users to follow discussions and receive notifications for new posts.",
|
||||
"type": "flarum-extension",
|
||||
"keywords": [
|
||||
"discussion"
|
||||
],
|
||||
"license": "MIT",
|
||||
"support": {
|
||||
"issues": "https://github.com/flarum/core/issues",
|
||||
"source": "https://github.com/flarum/subscriptions",
|
||||
"forum": "https://discuss.flarum.org"
|
||||
},
|
||||
"homepage": "https://flarum.org",
|
||||
"funding": [
|
||||
{
|
||||
"type": "website",
|
||||
"url": "https://flarum.org/donate/"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Flarum\\Subscriptions\\": "src/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.x-dev"
|
||||
},
|
||||
"flarum-extension": {
|
||||
"title": "Subscriptions",
|
||||
"category": "feature",
|
||||
"icon": {
|
||||
"name": "fas fa-star",
|
||||
"backgroundColor": "#ffea7b",
|
||||
"color": "#de8e00"
|
||||
}
|
||||
},
|
||||
"flarum-cli": {
|
||||
"modules": {
|
||||
"admin": false,
|
||||
"forum": true,
|
||||
"js": true,
|
||||
"jsCommon": false,
|
||||
"css": true,
|
||||
"gitConf": true,
|
||||
"githubActions": true,
|
||||
"prettier": true,
|
||||
"typescript": false,
|
||||
"bundlewatch": false,
|
||||
"backendTesting": false,
|
||||
"editorConfig": true,
|
||||
"styleci": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
64
extensions/subscriptions/extend.php
Normal file
64
extensions/subscriptions/extend.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Flarum\Api\Serializer\BasicDiscussionSerializer;
|
||||
use Flarum\Api\Serializer\DiscussionSerializer;
|
||||
use Flarum\Discussion\Discussion;
|
||||
use Flarum\Discussion\Event\Saving;
|
||||
use Flarum\Discussion\Filter\DiscussionFilterer;
|
||||
use Flarum\Discussion\Search\DiscussionSearcher;
|
||||
use Flarum\Extend;
|
||||
use Flarum\Post\Event\Deleted;
|
||||
use Flarum\Post\Event\Hidden;
|
||||
use Flarum\Post\Event\Posted;
|
||||
use Flarum\Post\Event\Restored;
|
||||
use Flarum\Subscriptions\HideIgnoredFromAllDiscussionsPage;
|
||||
use Flarum\Subscriptions\Listener;
|
||||
use Flarum\Subscriptions\Notification\NewPostBlueprint;
|
||||
use Flarum\Subscriptions\Query\SubscriptionFilterGambit;
|
||||
|
||||
return [
|
||||
(new Extend\Frontend('forum'))
|
||||
->js(__DIR__.'/js/dist/forum.js')
|
||||
->css(__DIR__.'/less/forum.less')
|
||||
->route('/following', 'following'),
|
||||
|
||||
new Extend\Locales(__DIR__.'/locale'),
|
||||
|
||||
(new Extend\View)
|
||||
->namespace('flarum-subscriptions', __DIR__.'/views'),
|
||||
|
||||
(new Extend\Notification())
|
||||
->type(NewPostBlueprint::class, BasicDiscussionSerializer::class, ['alert', 'email']),
|
||||
|
||||
(new Extend\ApiSerializer(DiscussionSerializer::class))
|
||||
->attribute('subscription', function (DiscussionSerializer $serializer, Discussion $discussion) {
|
||||
if ($state = $discussion->state) {
|
||||
return $state->subscription;
|
||||
}
|
||||
}),
|
||||
|
||||
(new Extend\User())
|
||||
->registerPreference('followAfterReply', 'boolval', false),
|
||||
|
||||
(new Extend\Event())
|
||||
->listen(Saving::class, Listener\SaveSubscriptionToDatabase::class)
|
||||
->listen(Posted::class, Listener\SendNotificationWhenReplyIsPosted::class)
|
||||
->listen(Hidden::class, Listener\DeleteNotificationWhenPostIsHiddenOrDeleted::class)
|
||||
->listen(Restored::class, Listener\RestoreNotificationWhenPostIsRestored::class)
|
||||
->listen(Deleted::class, Listener\DeleteNotificationWhenPostIsHiddenOrDeleted::class)
|
||||
->listen(Posted::class, Listener\FollowAfterReply::class),
|
||||
|
||||
(new Extend\Filter(DiscussionFilterer::class))
|
||||
->addFilter(SubscriptionFilterGambit::class)
|
||||
->addFilterMutator(HideIgnoredFromAllDiscussionsPage::class),
|
||||
|
||||
(new Extend\SimpleFlarumSearch(DiscussionSearcher::class))
|
||||
->addGambit(SubscriptionFilterGambit::class),
|
||||
];
|
9
extensions/subscriptions/js/.gitignore
vendored
Normal file
9
extensions/subscriptions/js/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
|
||||
node_modules
|
2
extensions/subscriptions/js/dist/forum.js
generated
vendored
Normal file
2
extensions/subscriptions/js/dist/forum.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
extensions/subscriptions/js/dist/forum.js.map
generated
vendored
Normal file
1
extensions/subscriptions/js/dist/forum.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
extensions/subscriptions/js/forum.js
Normal file
1
extensions/subscriptions/js/forum.js
Normal file
@@ -0,0 +1 @@
|
||||
export * from './src/forum';
|
19
extensions/subscriptions/js/package.json
Normal file
19
extensions/subscriptions/js/package.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@flarum/subscriptions",
|
||||
"prettier": "@flarum/prettier-config",
|
||||
"devDependencies": {
|
||||
"prettier": "^2.5.1",
|
||||
"flarum-webpack-config": "^2.0.0",
|
||||
"webpack": "^5.65.0",
|
||||
"webpack-cli": "^4.9.1",
|
||||
"@flarum/prettier-config": "^1.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "webpack --mode development --watch",
|
||||
"build": "webpack --mode production",
|
||||
"format": "prettier --write src",
|
||||
"format-check": "prettier --check src",
|
||||
"analyze": "cross-env ANALYZER=true yarn build"
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import Discussion from 'flarum/common/models/Discussion';
|
||||
import Badge from 'flarum/common/components/Badge';
|
||||
|
||||
export default function addSubscriptionBadge() {
|
||||
extend(Discussion.prototype, 'badges', function (badges) {
|
||||
let badge;
|
||||
|
||||
switch (this.subscription()) {
|
||||
case 'follow':
|
||||
badge = Badge.component({
|
||||
label: app.translator.trans('flarum-subscriptions.forum.badge.following_tooltip'),
|
||||
icon: 'fas fa-star',
|
||||
type: 'following',
|
||||
});
|
||||
break;
|
||||
|
||||
case 'ignore':
|
||||
badge = Badge.component({
|
||||
label: app.translator.trans('flarum-subscriptions.forum.badge.ignoring_tooltip'),
|
||||
icon: 'far fa-eye-slash',
|
||||
type: 'ignoring',
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
// no default
|
||||
}
|
||||
|
||||
if (badge) {
|
||||
badges.add('subscription', badge);
|
||||
}
|
||||
});
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import Button from 'flarum/common/components/Button';
|
||||
import DiscussionPage from 'flarum/forum/components/DiscussionPage';
|
||||
import DiscussionControls from 'flarum/forum/utils/DiscussionControls';
|
||||
|
||||
import SubscriptionMenu from './components/SubscriptionMenu';
|
||||
|
||||
export default function addSubscriptionControls() {
|
||||
extend(DiscussionControls, 'userControls', function (items, discussion, context) {
|
||||
if (app.session.user && !(context instanceof DiscussionPage)) {
|
||||
const states = {
|
||||
none: { label: app.translator.trans('flarum-subscriptions.forum.discussion_controls.follow_button'), icon: 'fas fa-star', save: 'follow' },
|
||||
follow: { label: app.translator.trans('flarum-subscriptions.forum.discussion_controls.unfollow_button'), icon: 'far fa-star', save: null },
|
||||
ignore: { label: app.translator.trans('flarum-subscriptions.forum.discussion_controls.unignore_button'), icon: 'fas fa-eye', save: null },
|
||||
};
|
||||
|
||||
const subscription = discussion.subscription() || 'none';
|
||||
|
||||
items.add(
|
||||
'subscription',
|
||||
Button.component(
|
||||
{
|
||||
icon: states[subscription].icon,
|
||||
onclick: discussion.save.bind(discussion, { subscription: states[subscription].save }),
|
||||
},
|
||||
states[subscription].label
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
extend(DiscussionPage.prototype, 'sidebarItems', function (items) {
|
||||
if (app.session.user) {
|
||||
const discussion = this.discussion;
|
||||
|
||||
items.add('subscription', SubscriptionMenu.component({ discussion }), 80);
|
||||
}
|
||||
});
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import LinkButton from 'flarum/common/components/LinkButton';
|
||||
import IndexPage from 'flarum/forum/components/IndexPage';
|
||||
import DiscussionListState from 'flarum/forum/states/DiscussionListState';
|
||||
import GlobalSearchState from 'flarum/forum/states/GlobalSearchState';
|
||||
|
||||
export default function addSubscriptionFilter() {
|
||||
extend(IndexPage.prototype, 'navItems', function (items) {
|
||||
if (app.session.user) {
|
||||
const params = app.search.stickyParams();
|
||||
|
||||
items.add(
|
||||
'following',
|
||||
LinkButton.component(
|
||||
{
|
||||
href: app.route('following', params),
|
||||
icon: 'fas fa-star',
|
||||
},
|
||||
app.translator.trans('flarum-subscriptions.forum.index.following_link')
|
||||
),
|
||||
50
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
extend(IndexPage.prototype, 'setTitle', function () {
|
||||
if (app.current.get('routeName') === 'following') {
|
||||
app.setTitle(app.translator.trans('flarum-subscriptions.forum.following.meta_title_text'));
|
||||
}
|
||||
});
|
||||
|
||||
extend(GlobalSearchState.prototype, 'params', function (params) {
|
||||
// We can't set `q` here directly, as that would make the search bar
|
||||
// think that text has been entered, and display the "clear" button.
|
||||
params.onFollowing = app.current.get('routeName') === 'following';
|
||||
});
|
||||
|
||||
extend(DiscussionListState.prototype, 'requestParams', function (params) {
|
||||
if (this.params.onFollowing) {
|
||||
params.filter.subscription = 'following';
|
||||
}
|
||||
});
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import SettingsPage from 'flarum/forum/components/SettingsPage';
|
||||
import Switch from 'flarum/common/components/Switch';
|
||||
|
||||
export default function () {
|
||||
extend(SettingsPage.prototype, 'notificationsItems', function (items) {
|
||||
items.add(
|
||||
'followAfterReply',
|
||||
Switch.component(
|
||||
{
|
||||
state: this.user.preferences().followAfterReply,
|
||||
onchange: (value) => {
|
||||
this.followAfterReplyLoading = true;
|
||||
|
||||
this.user.savePreferences({ followAfterReply: value }).then(() => {
|
||||
this.followAfterReplyLoading = false;
|
||||
m.redraw();
|
||||
});
|
||||
},
|
||||
loading: this.followAfterReplyLoading,
|
||||
},
|
||||
app.translator.trans('flarum-subscriptions.forum.settings.follow_after_reply_label')
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import Notification from 'flarum/forum/components/Notification';
|
||||
|
||||
export default class NewPostNotification extends Notification {
|
||||
icon() {
|
||||
return 'fas fa-star';
|
||||
}
|
||||
|
||||
href() {
|
||||
const notification = this.attrs.notification;
|
||||
const discussion = notification.subject();
|
||||
const content = notification.content() || {};
|
||||
|
||||
return app.route.discussion(discussion, content.postNumber);
|
||||
}
|
||||
|
||||
content() {
|
||||
return app.translator.trans('flarum-subscriptions.forum.notifications.new_post_text', { user: this.attrs.notification.fromUser() });
|
||||
}
|
||||
}
|
@@ -0,0 +1,115 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import Dropdown from 'flarum/common/components/Dropdown';
|
||||
import Button from 'flarum/common/components/Button';
|
||||
import Tooltip from 'flarum/common/components/Tooltip';
|
||||
import icon from 'flarum/common/helpers/icon';
|
||||
import extractText from 'flarum/common/utils/extractText';
|
||||
import classList from 'flarum/common/utils/classList';
|
||||
|
||||
import SubscriptionMenuItem from './SubscriptionMenuItem';
|
||||
|
||||
export default class SubscriptionMenu extends Dropdown {
|
||||
oninit(vnode) {
|
||||
super.oninit(vnode);
|
||||
|
||||
this.options = [
|
||||
{
|
||||
subscription: null,
|
||||
icon: 'far fa-star',
|
||||
label: app.translator.trans('flarum-subscriptions.forum.sub_controls.not_following_button'),
|
||||
description: app.translator.trans('flarum-subscriptions.forum.sub_controls.not_following_text'),
|
||||
},
|
||||
{
|
||||
subscription: 'follow',
|
||||
icon: 'fas fa-star',
|
||||
label: app.translator.trans('flarum-subscriptions.forum.sub_controls.following_button'),
|
||||
description: app.translator.trans('flarum-subscriptions.forum.sub_controls.following_text'),
|
||||
},
|
||||
{
|
||||
subscription: 'ignore',
|
||||
icon: 'far fa-eye-slash',
|
||||
label: app.translator.trans('flarum-subscriptions.forum.sub_controls.ignoring_button'),
|
||||
description: app.translator.trans('flarum-subscriptions.forum.sub_controls.ignoring_text'),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
view() {
|
||||
const discussion = this.attrs.discussion;
|
||||
const subscription = discussion.subscription();
|
||||
|
||||
let buttonLabel = app.translator.trans('flarum-subscriptions.forum.sub_controls.follow_button');
|
||||
let buttonIcon = 'far fa-star';
|
||||
const buttonClass = 'SubscriptionMenu-button--' + subscription;
|
||||
|
||||
switch (subscription) {
|
||||
case 'follow':
|
||||
buttonLabel = app.translator.trans('flarum-subscriptions.forum.sub_controls.following_button');
|
||||
buttonIcon = 'fas fa-star';
|
||||
break;
|
||||
|
||||
case 'ignore':
|
||||
buttonLabel = app.translator.trans('flarum-subscriptions.forum.sub_controls.ignoring_button');
|
||||
buttonIcon = 'far fa-eye-slash';
|
||||
break;
|
||||
|
||||
default:
|
||||
// no default
|
||||
}
|
||||
|
||||
const preferences = app.session.user.preferences();
|
||||
const notifyEmail = preferences['notify_newPost_email'];
|
||||
const notifyAlert = preferences['notify_newPost_alert'];
|
||||
const tooltipText = extractText(
|
||||
app.translator.trans(
|
||||
notifyEmail ? 'flarum-subscriptions.forum.sub_controls.notify_email_tooltip' : 'flarum-subscriptions.forum.sub_controls.notify_alert_tooltip'
|
||||
)
|
||||
);
|
||||
|
||||
const shouldShowTooltip = (notifyEmail || notifyAlert) && subscription === null;
|
||||
|
||||
const button = (
|
||||
<Button
|
||||
className={classList('Button', 'SubscriptionMenu-button', buttonClass)}
|
||||
icon={buttonIcon}
|
||||
onclick={this.saveSubscription.bind(this, discussion, ['follow', 'ignore'].indexOf(subscription) !== -1 ? null : 'follow')}
|
||||
>
|
||||
{buttonLabel}
|
||||
</Button>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="Dropdown ButtonGroup SubscriptionMenu">
|
||||
{shouldShowTooltip ? (
|
||||
<Tooltip text={tooltipText} position="bottom">
|
||||
{button}
|
||||
</Tooltip>
|
||||
) : (
|
||||
button
|
||||
)}
|
||||
|
||||
<button className={classList('Dropdown-toggle Button Button--icon', buttonClass)} data-toggle="dropdown">
|
||||
{icon('fas fa-caret-down', { className: 'Button-icon' })}
|
||||
</button>
|
||||
|
||||
<ul className="Dropdown-menu dropdown-menu Dropdown-menu--right">
|
||||
{this.options.map((attrs) => (
|
||||
<li>
|
||||
{SubscriptionMenuItem.component({
|
||||
...attrs,
|
||||
onclick: this.saveSubscription.bind(this, discussion, attrs.subscription),
|
||||
active: subscription === attrs.subscription,
|
||||
})}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
saveSubscription(discussion, subscription) {
|
||||
discussion.save({ subscription });
|
||||
|
||||
this.$('.SubscriptionMenu-button').tooltip('hide');
|
||||
}
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
import Component from 'flarum/common/Component';
|
||||
import icon from 'flarum/common/helpers/icon';
|
||||
|
||||
export default class SubscriptionMenuItem extends Component {
|
||||
view() {
|
||||
return (
|
||||
<button className="SubscriptionMenuItem hasIcon" onclick={this.attrs.onclick}>
|
||||
{this.attrs.active ? icon('fas fa-check', { className: 'Button-icon' }) : ''}
|
||||
<span className="SubscriptionMenuItem-label">
|
||||
{icon(this.attrs.icon, { className: 'Button-icon' })}
|
||||
<strong>{this.attrs.label}</strong>
|
||||
<span className="SubscriptionMenuItem-description">{this.attrs.description}</span>
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
33
extensions/subscriptions/js/src/forum/index.js
Normal file
33
extensions/subscriptions/js/src/forum/index.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import app from 'flarum/forum/app';
|
||||
import Model from 'flarum/common/Model';
|
||||
import Discussion from 'flarum/common/models/Discussion';
|
||||
import IndexPage from 'flarum/forum/components/IndexPage';
|
||||
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
||||
|
||||
import addSubscriptionBadge from './addSubscriptionBadge';
|
||||
import addSubscriptionControls from './addSubscriptionControls';
|
||||
import addSubscriptionFilter from './addSubscriptionFilter';
|
||||
import addSubscriptionSettings from './addSubscriptionSettings';
|
||||
|
||||
import NewPostNotification from './components/NewPostNotification';
|
||||
|
||||
app.initializers.add('subscriptions', function () {
|
||||
app.routes.following = { path: '/following', component: IndexPage };
|
||||
app.notificationComponents.newPost = NewPostNotification;
|
||||
|
||||
Discussion.prototype.subscription = Model.attribute('subscription');
|
||||
|
||||
addSubscriptionBadge();
|
||||
addSubscriptionControls();
|
||||
addSubscriptionFilter();
|
||||
addSubscriptionSettings();
|
||||
|
||||
extend(NotificationGrid.prototype, 'notificationTypes', function (items) {
|
||||
items.add('newPost', {
|
||||
name: 'newPost',
|
||||
icon: 'fas fa-star',
|
||||
label: app.translator.trans('flarum-subscriptions.forum.settings.notify_new_post_label'),
|
||||
});
|
||||
});
|
||||
});
|
1
extensions/subscriptions/js/webpack.config.js
Normal file
1
extensions/subscriptions/js/webpack.config.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require('flarum-webpack-config')();
|
2284
extensions/subscriptions/js/yarn.lock
Normal file
2284
extensions/subscriptions/js/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
39
extensions/subscriptions/less/forum.less
Normal file
39
extensions/subscriptions/less/forum.less
Normal file
@@ -0,0 +1,39 @@
|
||||
:root {
|
||||
--following-bg: #ffea7b;
|
||||
--following-color: #de8e00;
|
||||
--ignoring-bg: #aaa;
|
||||
}
|
||||
|
||||
.Badge--following {
|
||||
--badge-bg: var(--following-bg);
|
||||
--badge-color: var(--following-color);
|
||||
}
|
||||
.Badge--ignoring {
|
||||
--badge-bg: var(--ignoring-bg);
|
||||
}
|
||||
.SubscriptionMenu-button--follow {
|
||||
& when (@config-dark-mode = false) {
|
||||
.Button--color(#de8e00, #fff2ae);
|
||||
}
|
||||
& when (@config-dark-mode = true) {
|
||||
.Button--color(#784d00, #fbb94c);
|
||||
}
|
||||
}
|
||||
.SubscriptionMenu .Dropdown-menu {
|
||||
min-width: 260px;
|
||||
}
|
||||
.SubscriptionMenuItem-label {
|
||||
padding-left: 25px;
|
||||
display: block;
|
||||
white-space: normal;
|
||||
|
||||
& strong {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.SubscriptionMenuItem-description {
|
||||
display: block;
|
||||
color: @muted-color;
|
||||
font-size: 12px;
|
||||
margin-top: 3px;
|
||||
}
|
80
extensions/subscriptions/locale/en.yml
Normal file
80
extensions/subscriptions/locale/en.yml
Normal file
@@ -0,0 +1,80 @@
|
||||
flarum-subscriptions:
|
||||
|
||||
##
|
||||
# UNIQUE KEYS - The following keys are used in only one location each.
|
||||
##
|
||||
|
||||
# Translations in this namespace are used by the forum user interface.
|
||||
forum:
|
||||
|
||||
# These translations are displayed as tooltips for discussion badges.
|
||||
badge:
|
||||
following_tooltip: => flarum-subscriptions.ref.following
|
||||
ignoring_tooltip: => flarum-subscriptions.ref.ignoring
|
||||
|
||||
# These translations are used by the discussion control buttons.
|
||||
discussion_controls:
|
||||
follow_button: => flarum-subscriptions.ref.follow
|
||||
unfollow_button: Unfollow
|
||||
unignore_button: Unignore
|
||||
|
||||
# These translations are used on the page that displays all subscriptions.
|
||||
following:
|
||||
meta_title_text: => flarum-subscriptions.ref.following
|
||||
|
||||
# These translations are used on the index page, peripheral to the discussion list.
|
||||
index:
|
||||
following_link: => flarum-subscriptions.ref.following
|
||||
|
||||
# These translations are used by the Notifications dropdown, a.k.a. "the bell".
|
||||
notifications:
|
||||
new_post_text: "{username} posted"
|
||||
|
||||
# These translations are used in the Settings page.
|
||||
settings:
|
||||
follow_after_reply_label: Automatically follow discussions that I reply to
|
||||
notify_new_post_label: Someone posts in a discussion I'm following
|
||||
|
||||
# These translations are used in the subscription menu displayed to the right of the post stream.
|
||||
sub_controls:
|
||||
follow_button: => flarum-subscriptions.ref.follow
|
||||
following_button: => flarum-subscriptions.ref.following
|
||||
following_text: Be notified of all replies.
|
||||
ignoring_button: => flarum-subscriptions.ref.ignoring
|
||||
ignoring_text: Never be notified. Hide from the discussion list.
|
||||
not_following_button: Not Following
|
||||
not_following_text: "Be notified only when @mentioned."
|
||||
notify_alert_tooltip: Get a forum notification when there are new posts
|
||||
notify_email_tooltip: Get an email when there are new posts
|
||||
|
||||
# Translations in this namespace are used in emails sent by the forum.
|
||||
email:
|
||||
|
||||
# These translations are used in emails sent when a post is made in a subscribed discussion
|
||||
new_post:
|
||||
subject: "[New Post] {title}"
|
||||
body: |
|
||||
Hey {recipient_display_name}!
|
||||
|
||||
{poster_display_name} made a post in a discussion you're following: {title}.
|
||||
|
||||
To view the new activity, check out the following link:
|
||||
{url}
|
||||
|
||||
---
|
||||
|
||||
{content}
|
||||
|
||||
---
|
||||
|
||||
You won't receive any more notifications about this discussion until you're up-to-date.
|
||||
|
||||
##
|
||||
# REUSED TRANSLATIONS - These keys should not be used directly in code!
|
||||
##
|
||||
|
||||
# Translations in this namespace are referenced by two or more unique keys.
|
||||
ref:
|
||||
follow: Follow
|
||||
following: Following
|
||||
ignoring: Ignoring
|
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Flarum\Database\Migration;
|
||||
|
||||
return Migration::addColumns('discussion_user', [
|
||||
'subscription' => ['enum', 'allowed' => ['follow', 'ignore'], 'nullable' => true]
|
||||
]);
|
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Subscriptions;
|
||||
|
||||
use Flarum\Filter\FilterState;
|
||||
use Flarum\Query\QueryCriteria;
|
||||
|
||||
class HideIgnoredFromAllDiscussionsPage
|
||||
{
|
||||
public function __invoke(FilterState $filterState, QueryCriteria $criteria)
|
||||
{
|
||||
// We only want to hide on the "all discussions" page.
|
||||
if (count($filterState->getActiveFilters()) === 0) {
|
||||
// TODO: might be better as `id IN (subquery)`?
|
||||
$actor = $filterState->getActor();
|
||||
$filterState->getQuery()->whereNotExists(function ($query) use ($actor) {
|
||||
$query->selectRaw(1)
|
||||
->from('discussion_user')
|
||||
->whereColumn('discussions.id', 'discussion_id')
|
||||
->where('user_id', $actor->id)
|
||||
->where('subscription', 'ignore');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
60
extensions/subscriptions/src/Job/SendReplyNotification.php
Normal file
60
extensions/subscriptions/src/Job/SendReplyNotification.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Subscriptions\Job;
|
||||
|
||||
use Flarum\Notification\NotificationSyncer;
|
||||
use Flarum\Post\Post;
|
||||
use Flarum\Subscriptions\Notification\NewPostBlueprint;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SendReplyNotification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var Post
|
||||
*/
|
||||
protected $post;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $lastPostNumber;
|
||||
|
||||
/**
|
||||
* @param Post $post
|
||||
* @param int|null $lastPostNumber
|
||||
*/
|
||||
public function __construct(Post $post, $lastPostNumber)
|
||||
{
|
||||
$this->post = $post;
|
||||
$this->lastPostNumber = $lastPostNumber;
|
||||
}
|
||||
|
||||
public function handle(NotificationSyncer $notifications)
|
||||
{
|
||||
$post = $this->post;
|
||||
$discussion = $post->discussion;
|
||||
|
||||
$notify = $discussion->readers()
|
||||
->where('users.id', '!=', $post->user_id)
|
||||
->where('discussion_user.subscription', 'follow')
|
||||
->where('discussion_user.last_read_post_number', $this->lastPostNumber)
|
||||
->get();
|
||||
|
||||
$notifications->sync(
|
||||
new NewPostBlueprint($post),
|
||||
$notify->all()
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Subscriptions\Listener;
|
||||
|
||||
use Flarum\Notification\NotificationSyncer;
|
||||
use Flarum\Post\Event\Deleted;
|
||||
use Flarum\Post\Event\Hidden;
|
||||
use Flarum\Subscriptions\Notification\NewPostBlueprint;
|
||||
|
||||
class DeleteNotificationWhenPostIsHiddenOrDeleted
|
||||
{
|
||||
/**
|
||||
* @var NotificationSyncer
|
||||
*/
|
||||
protected $notifications;
|
||||
|
||||
/**
|
||||
* @param NotificationSyncer $notifications
|
||||
*/
|
||||
public function __construct(NotificationSyncer $notifications)
|
||||
{
|
||||
$this->notifications = $notifications;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Hidden|Deleted $event
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
$this->notifications->delete(new NewPostBlueprint($event->post));
|
||||
}
|
||||
}
|
29
extensions/subscriptions/src/Listener/FollowAfterReply.php
Normal file
29
extensions/subscriptions/src/Listener/FollowAfterReply.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Subscriptions\Listener;
|
||||
|
||||
use Flarum\Post\Event\Posted;
|
||||
|
||||
class FollowAfterReply
|
||||
{
|
||||
public function handle(Posted $event)
|
||||
{
|
||||
$actor = $event->actor;
|
||||
|
||||
if ($actor && $actor->exists && $actor->getPreference('followAfterReply')) {
|
||||
$actor->assertRegistered();
|
||||
|
||||
$state = $event->post->discussion->stateFor($actor);
|
||||
|
||||
$state->subscription = 'follow';
|
||||
$state->save();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Subscriptions\Listener;
|
||||
|
||||
use Flarum\Notification\NotificationSyncer;
|
||||
use Flarum\Post\Event\Restored;
|
||||
use Flarum\Subscriptions\Notification\NewPostBlueprint;
|
||||
|
||||
class RestoreNotificationWhenPostIsRestored
|
||||
{
|
||||
/**
|
||||
* @var NotificationSyncer
|
||||
*/
|
||||
protected $notifications;
|
||||
|
||||
/**
|
||||
* @param NotificationSyncer $notifications
|
||||
*/
|
||||
public function __construct(NotificationSyncer $notifications)
|
||||
{
|
||||
$this->notifications = $notifications;
|
||||
}
|
||||
|
||||
public function handle(Restored $event)
|
||||
{
|
||||
$this->notifications->restore(new NewPostBlueprint($event->post));
|
||||
}
|
||||
}
|
37
extensions/subscriptions/src/Listener/SaveSubscriptionToDatabase.php
Executable file
37
extensions/subscriptions/src/Listener/SaveSubscriptionToDatabase.php
Executable file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Subscriptions\Listener;
|
||||
|
||||
use Flarum\Discussion\Event\Saving;
|
||||
|
||||
class SaveSubscriptionToDatabase
|
||||
{
|
||||
public function handle(Saving $event)
|
||||
{
|
||||
$discussion = $event->discussion;
|
||||
$data = $event->data;
|
||||
|
||||
if (array_key_exists('subscription', $data['attributes'])) {
|
||||
$actor = $event->actor;
|
||||
$subscription = $data['attributes']['subscription'];
|
||||
|
||||
$actor->assertRegistered();
|
||||
|
||||
$state = $discussion->stateFor($actor);
|
||||
|
||||
if (! in_array($subscription, ['follow', 'ignore'])) {
|
||||
$subscription = null;
|
||||
}
|
||||
|
||||
$state->subscription = $subscription;
|
||||
$state->save();
|
||||
}
|
||||
}
|
||||
}
|
34
extensions/subscriptions/src/Listener/SendNotificationWhenReplyIsPosted.php
Executable file
34
extensions/subscriptions/src/Listener/SendNotificationWhenReplyIsPosted.php
Executable file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Subscriptions\Listener;
|
||||
|
||||
use Flarum\Post\Event\Posted;
|
||||
use Flarum\Subscriptions\Job\SendReplyNotification;
|
||||
use Illuminate\Contracts\Queue\Queue;
|
||||
|
||||
class SendNotificationWhenReplyIsPosted
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
protected $queue;
|
||||
|
||||
public function __construct(Queue $queue)
|
||||
{
|
||||
$this->queue = $queue;
|
||||
}
|
||||
|
||||
public function handle(Posted $event)
|
||||
{
|
||||
$this->queue->push(
|
||||
new SendReplyNotification($event->post, $event->post->discussion->last_post_number)
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Subscriptions\Notification;
|
||||
|
||||
use Flarum\Discussion\Discussion;
|
||||
use Flarum\Notification\Blueprint\BlueprintInterface;
|
||||
use Flarum\Notification\MailableInterface;
|
||||
use Flarum\Post\Post;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class NewPostBlueprint implements BlueprintInterface, MailableInterface
|
||||
{
|
||||
/**
|
||||
* @var Post
|
||||
*/
|
||||
public $post;
|
||||
|
||||
/**
|
||||
* @param Post $post
|
||||
*/
|
||||
public function __construct(Post $post)
|
||||
{
|
||||
$this->post = $post;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSubject()
|
||||
{
|
||||
return $this->post->discussion;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFromUser()
|
||||
{
|
||||
return $this->post->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return ['postNumber' => (int) $this->post->number];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getEmailView()
|
||||
{
|
||||
return ['text' => 'flarum-subscriptions::emails.newPost'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getEmailSubject(TranslatorInterface $translator)
|
||||
{
|
||||
return $translator->trans('flarum-subscriptions.email.new_post.subject', ['{title}' => $this->post->discussion->title]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getType()
|
||||
{
|
||||
return 'newPost';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubjectModel()
|
||||
{
|
||||
return Discussion::class;
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Subscriptions\Query;
|
||||
|
||||
use Flarum\Filter\FilterInterface;
|
||||
use Flarum\Filter\FilterState;
|
||||
use Flarum\Search\AbstractRegexGambit;
|
||||
use Flarum\Search\SearchState;
|
||||
use Flarum\User\User;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
|
||||
class SubscriptionFilterGambit extends AbstractRegexGambit implements FilterInterface
|
||||
{
|
||||
protected function getGambitPattern()
|
||||
{
|
||||
return 'is:(follow|ignor)(?:ing|ed)';
|
||||
}
|
||||
|
||||
protected function conditions(SearchState $search, array $matches, $negate)
|
||||
{
|
||||
$this->constrain($search->getQuery(), $search->getActor(), $matches[1], $negate);
|
||||
}
|
||||
|
||||
public function getFilterKey(): string
|
||||
{
|
||||
return 'subscription';
|
||||
}
|
||||
|
||||
public function filter(FilterState $filterState, string $filterValue, bool $negate)
|
||||
{
|
||||
preg_match('/^'.$this->getGambitPattern().'$/i', 'is:'.$filterValue, $matches);
|
||||
|
||||
$this->constrain($filterState->getQuery(), $filterState->getActor(), $matches[1], $negate);
|
||||
}
|
||||
|
||||
protected function constrain(Builder $query, User $actor, string $subscriptionType, bool $negate)
|
||||
{
|
||||
$method = $negate ? 'whereNotIn' : 'whereIn';
|
||||
$query->$method('id', function ($query) use ($actor, $subscriptionType) {
|
||||
$query->select('discussion_id')
|
||||
->from('discussion_user')
|
||||
->where('user_id', $actor->id)
|
||||
->where('subscription', $subscriptionType === 'follow' ? 'follow' : 'ignore');
|
||||
});
|
||||
}
|
||||
}
|
7
extensions/subscriptions/views/emails/newPost.blade.php
Normal file
7
extensions/subscriptions/views/emails/newPost.blade.php
Normal file
@@ -0,0 +1,7 @@
|
||||
{!! $translator->trans('flarum-subscriptions.email.new_post.body', [
|
||||
'{recipient_display_name}' => $user->display_name,
|
||||
'{poster_display_name}' => $blueprint->post->user->display_name,
|
||||
'{title}' => $blueprint->post->discussion->title,
|
||||
'{url}' => $url->to('forum')->route('discussion', ['id' => $blueprint->post->discussion_id, 'near' => $blueprint->post->number]),
|
||||
'{content}' => $blueprint->post->content
|
||||
]) !!}
|
Reference in New Issue
Block a user