mirror of
https://github.com/flarum/core.git
synced 2025-08-14 04:14:06 +02:00
Compare commits
172 Commits
v1.5.0
...
sm/priorit
Author | SHA1 | Date | |
---|---|---|---|
|
7ddc8a60dd | ||
|
79a9b23096 | ||
|
33e2bd1a77 | ||
|
a3a39caa44 | ||
|
bbf873442a | ||
|
d35bb873a8 | ||
|
598ff21d7d | ||
|
9342903d68 | ||
|
ea7b270f47 | ||
|
906b0fb633 | ||
|
408a92b4ea | ||
|
0da069ba9f | ||
|
d8fa791d9c | ||
|
fee6ffe396 | ||
|
7a60a529da | ||
|
37fd218723 | ||
|
1ee5cf6ba9 | ||
|
ced1c2d94f | ||
|
f8d856028d | ||
|
748cca6d12 | ||
|
f4f8369dc0 | ||
|
aa0b3288d5 | ||
|
153bb1a53c | ||
|
ee1e04cdc2 | ||
|
77a0b11bc8 | ||
|
7e6458a125 | ||
|
675cdab658 | ||
|
e7fc29a59f | ||
|
08dead81ce | ||
|
47b670aa29 | ||
|
f9a5d485c3 | ||
|
5717a74fcc | ||
|
2e0f026dde | ||
|
bf52743510 | ||
|
da1bf8da21 | ||
|
ccf9442d79 | ||
|
4bb3b2235d | ||
|
03d2d7eabb | ||
|
4d292263b5 | ||
|
6adae00f72 | ||
|
d7f4975330 | ||
|
5fe3cfd837 | ||
|
2d2bf5c504 | ||
|
a4f4ee8e71 | ||
|
4a38047bfb | ||
|
d5e6f6db5f | ||
|
20e7d245da | ||
|
243bc139b0 | ||
|
adf78bbd95 | ||
|
c8d9f1111e | ||
|
e5f05166a0 | ||
|
02556c6ca6 | ||
|
666223fa8c | ||
|
12dfcc5c79 | ||
|
248a71d9b5 | ||
|
a131e87911 | ||
|
be63b28437 | ||
|
132fdea659 | ||
|
fe8480c8f7 | ||
|
1e8a0f930d | ||
|
d7b9a03f31 | ||
|
78189f29d2 | ||
|
07f8b6161a | ||
|
0eff1f6b2d | ||
|
a53a0db2b7 | ||
|
a129999132 | ||
|
8f80cde5b7 | ||
|
4de3cd4d9c | ||
|
3dd2cadb9b | ||
|
605225c851 | ||
|
f33fbdd0b5 | ||
|
5bc47c0278 | ||
|
0e238a9c82 | ||
|
64fa35f2f3 | ||
|
c99d04fce2 | ||
|
67c0d75ebc | ||
|
6f4f964ce8 | ||
|
67dd2c21b6 | ||
|
e5d2b8cad9 | ||
|
f5c346f1c7 | ||
|
5bb0593bad | ||
|
47d2053766 | ||
|
e0b9dcfbcd | ||
|
8a65ad980d | ||
|
9a0668effd | ||
|
224b122303 | ||
|
ed0cee97f5 | ||
|
543c5f2a2e | ||
|
690de9ce0f | ||
|
50253a2eb8 | ||
|
92473c0967 | ||
|
361234205c | ||
|
54798aaa47 | ||
|
fe5d543864 | ||
|
2517bc0f70 | ||
|
b5f324a7b3 | ||
|
8ef0df94b2 | ||
|
c50c924242 | ||
|
18bdd48835 | ||
|
f49cf887dc | ||
|
19793d5617 | ||
|
4a2f48ad04 | ||
|
2b413b06c5 | ||
|
2b89dedc08 | ||
|
00a880c467 | ||
|
92d2adc5fd | ||
|
bc59b8d9ab | ||
|
bb9f01372f | ||
|
069a29d22a | ||
|
105170b5bc | ||
|
b8261ef055 | ||
|
d14770188b | ||
|
e9bb646dbf | ||
|
46adf40675 | ||
|
6938a13223 | ||
|
ab56aefeaa | ||
|
259db92b9a | ||
|
094ec77980 | ||
|
bb712693d4 | ||
|
1e00e3fdbb | ||
|
47d7a6e155 | ||
|
45d91212f6 | ||
|
1a81c98d43 | ||
|
c98e6ba5a7 | ||
|
eeb00cc56b | ||
|
87cdb5b4d8 | ||
|
bc4b0b864c | ||
|
53ab1503e4 | ||
|
62a396e434 | ||
|
2096fa2807 | ||
|
06963df407 | ||
|
8fe09815f5 | ||
|
fccc3e2188 | ||
|
f0a867b20f | ||
|
69311ae689 | ||
|
f005b9e031 | ||
|
31ced98e0d | ||
|
9964ddd731 | ||
|
32ac0a8d8f | ||
|
827e905f8e | ||
|
cdc76567d4 | ||
|
5898a50463 | ||
|
72d9ee2010 | ||
|
4e5e4e5c6e | ||
|
201d7430fe | ||
|
52f6148876 | ||
|
dc215aba59 | ||
|
90a68506b8 | ||
|
bd0577f435 | ||
|
d33f1abffc | ||
|
b0b47a0888 | ||
|
8c0a14aff2 | ||
|
76788efaba | ||
|
973ec32e13 | ||
|
cf818aae9e | ||
|
6da0bc63b7 | ||
|
6e1bc2daed | ||
|
7ce9d63ed6 | ||
|
267f6759f8 | ||
|
b5874a08e4 | ||
|
368e08bb9b | ||
|
5f2d7fb7b6 | ||
|
68d6e30143 | ||
|
c5c312db0d | ||
|
05f80b7b83 | ||
|
31c3cfc4ea | ||
|
fd196454a5 | ||
|
f6761843b2 | ||
|
84c31165e5 | ||
|
fc4d5e3d43 | ||
|
b2fa28e4b5 | ||
|
fc743ba888 |
@@ -18,5 +18,8 @@ trim_trailing_whitespace = false
|
||||
[*.{php,xml,json}]
|
||||
indent_size = 4
|
||||
|
||||
[tsconfig.json]
|
||||
[{tsconfig.json,prettierrc.json}]
|
||||
indent_size = 2
|
||||
|
||||
[*.neon]
|
||||
indent_style = tab
|
||||
|
64
.github/workflows/REUSABLE_backend.yml
vendored
64
.github/workflows/REUSABLE_backend.yml
vendored
@@ -9,6 +9,12 @@ on:
|
||||
default: true
|
||||
required: false
|
||||
|
||||
enable_phpstan:
|
||||
description: "Enable PHPStan Static Analysis?"
|
||||
type: boolean
|
||||
default: false
|
||||
required: false
|
||||
|
||||
backend_directory:
|
||||
description: The directory of the project where backend code is located. This should contain a `composer.json` file, and is generally the root directory of the repo.
|
||||
type: string
|
||||
@@ -19,7 +25,14 @@ on:
|
||||
description: Versions of PHP to test with. Should be array of strings encoded as JSON array
|
||||
type: string
|
||||
required: false
|
||||
default: '["7.3", "7.4", "8.0", "8.1"]'
|
||||
default: '["7.3", "7.4", "8.0", "8.1", "8.2"]'
|
||||
|
||||
php_extensions:
|
||||
description: PHP extensions to install.
|
||||
type: string
|
||||
required: false
|
||||
default: 'curl, dom, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip'
|
||||
|
||||
db_versions:
|
||||
description: Versions of databases to test with. Should be array of strings encoded as JSON array
|
||||
type: string
|
||||
@@ -45,6 +58,7 @@ jobs:
|
||||
php: ${{ fromJSON(inputs.php_versions) }}
|
||||
service: ${{ fromJSON(inputs.db_versions) }}
|
||||
prefix: ['']
|
||||
php_ini_values: [inputs.php_ini_values]
|
||||
|
||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixinclude
|
||||
include:
|
||||
@@ -73,12 +87,24 @@ jobs:
|
||||
prefix: flarum_
|
||||
prefixStr: (prefix)
|
||||
|
||||
# @TODO: remove in 2.0
|
||||
# Include testing PHP 8.2 with deprecation warnings disabled.
|
||||
- php: 8.2
|
||||
php_ini_values: error_reporting=E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED
|
||||
|
||||
# To reduce number of actions, we exclude some PHP versions from running with some DB versions.
|
||||
exclude:
|
||||
- php: ${{ fromJSON(inputs.php_versions)[1] }}
|
||||
service: 'mysql:8.0.30'
|
||||
- php: ${{ fromJSON(inputs.php_versions)[2] }}
|
||||
service: 'mysql:8.0.30'
|
||||
- php: ${{ fromJSON(inputs.php_versions)[3] }}
|
||||
service: 'mysql:8.0.30'
|
||||
|
||||
# @TODO: remove in 2.0
|
||||
# Exclude testing PHP 8.2 with deprecation warnings enabled.
|
||||
- php: 8.2
|
||||
php_ini_values: error_reporting=E_ALL
|
||||
|
||||
services:
|
||||
mysql:
|
||||
@@ -100,9 +126,9 @@ jobs:
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
coverage: xdebug
|
||||
extensions: curl, dom, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip
|
||||
extensions: ${{ inputs.php_extensions }}
|
||||
tools: phpunit, composer:v2
|
||||
ini-values: ${{ inputs.php_ini_values }}
|
||||
ini-values: ${{ matrix.php_ini_values }}
|
||||
|
||||
# The authentication alter is necessary because newer mysql versions use the `caching_sha2_password` driver,
|
||||
# which isn't supported prior to PHP7.4
|
||||
@@ -130,3 +156,35 @@ jobs:
|
||||
working-directory: ${{ inputs.backend_directory }}
|
||||
env:
|
||||
COMPOSER_PROCESS_TIMEOUT: 600
|
||||
|
||||
phpstan:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php: ${{ fromJSON(inputs.php_versions) }}
|
||||
|
||||
name: 'PHPStan PHP ${{ matrix.php }}'
|
||||
|
||||
if: >-
|
||||
inputs.enable_phpstan &&
|
||||
((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || github.event_name != 'pull_request')
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
coverage: xdebug
|
||||
extensions: ${{ inputs.php_extensions }}
|
||||
tools: phpunit, composer:v2
|
||||
ini-values: ${{ matrix.php_ini_values }}
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install
|
||||
working-directory: ${{ inputs.backend_directory }}
|
||||
|
||||
- name: Run PHPStan
|
||||
run: composer analyse:phpstan
|
||||
|
17
.github/workflows/REUSABLE_frontend.yml
vendored
17
.github/workflows/REUSABLE_frontend.yml
vendored
@@ -28,6 +28,11 @@ on:
|
||||
type: string
|
||||
required: false
|
||||
default: check-typings-coverage
|
||||
test_script:
|
||||
description: "Script to run for tests. Empty value to disable."
|
||||
type: string
|
||||
required: false
|
||||
default: test
|
||||
|
||||
enable_bundlewatch:
|
||||
description: "Enable Bundlewatch?"
|
||||
@@ -44,6 +49,11 @@ on:
|
||||
type: boolean
|
||||
default: true
|
||||
required: false
|
||||
enable_tests:
|
||||
description: "Enable Tests?"
|
||||
type: boolean
|
||||
default: false
|
||||
required: false
|
||||
|
||||
backend_directory:
|
||||
description: The directory of the project where backend code is located. This should contain a `composer.json` file, and is generally the root directory of the repo.
|
||||
@@ -96,10 +106,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ inputs.node_version }}
|
||||
cache: ${{ inputs.js_package_manager }}
|
||||
@@ -122,7 +132,7 @@ jobs:
|
||||
working-directory: ${{ inputs.frontend_directory }}
|
||||
|
||||
- name: JS Checks & Production Build
|
||||
uses: flarum/action-build@3
|
||||
uses: flarum/action-build@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
build_script: ${{ inputs.build_script }}
|
||||
@@ -130,6 +140,7 @@ jobs:
|
||||
format_script: ${{ inputs.enable_prettier == true && inputs.format_script || '' }}
|
||||
check_typings_script: ${{ inputs.enable_typescript == true && inputs.check_typings_script || '' }}
|
||||
type_coverage_script: ${{ inputs.enable_typescript == true && inputs.type_coverage_script || '' }}
|
||||
test_script: ${{ inputs.enable_tests == true && inputs.test_script || '' }}
|
||||
package_manager: ${{ inputs.js_package_manager }}
|
||||
js_path: ${{ inputs.frontend_directory }}
|
||||
do_not_commit: ${{ github.ref != format('refs/heads/{0}', inputs.main_git_branch) || github.event_name != 'push' }}
|
||||
|
@@ -6,6 +6,6 @@ jobs:
|
||||
run:
|
||||
uses: ./.github/workflows/REUSABLE_backend.yml
|
||||
with:
|
||||
enable_backend_testing: true
|
||||
enable_backend_testing: false
|
||||
|
||||
backend_directory: ./extensions/package-manager
|
||||
|
3
.github/workflows/frontend.yml
vendored
3
.github/workflows/frontend.yml
vendored
@@ -11,6 +11,9 @@ jobs:
|
||||
js_package_manager: yarn
|
||||
cache_dependency_path: ./yarn.lock
|
||||
main_git_branch: main
|
||||
enable_tests: true
|
||||
# @TODO: fix bundlewatch
|
||||
enable_bundlewatch: false
|
||||
|
||||
secrets:
|
||||
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}
|
||||
|
12
.github/workflows/phpstan.yml
vendored
Normal file
12
.github/workflows/phpstan.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
name: Framework PHP
|
||||
|
||||
on: [workflow_dispatch, push, pull_request]
|
||||
|
||||
jobs:
|
||||
run:
|
||||
uses: ./.github/workflows/REUSABLE_backend.yml
|
||||
with:
|
||||
enable_backend_testing: false
|
||||
enable_phpstan: true
|
||||
|
||||
backend_directory: .
|
56
CHANGELOG.md
56
CHANGELOG.md
@@ -1,5 +1,60 @@
|
||||
# Changelog
|
||||
|
||||
# [v1.6.3](https://github.com/flarum/framework/compare/v1.6.2...v1.6.3)
|
||||
### Fixed
|
||||
* Post mentions can be used to read any post on the forum without access control (ab1c868b978e8b0d09a5d682c54665dae17d0985).
|
||||
* Notifications can leak restricted content (d0a2b95dca57d3dae9a0d77b610b1cb1d0b1766a).
|
||||
* Any user including unactivated can reply in public discussions whose first post was permanently deleted (12f14112a0ecd1484d97330b82beb2a145919015).
|
||||
* (subscriptions) Post notifications not getting access checked (https://github.com/flarum/framework/commit/e5f05166a062a9a6eb7c12e28728bfd5db7270e3).
|
||||
|
||||
## [v1.6.2](https://github.com/flarum/framework/compare/v1.6.1...v1.6.2)
|
||||
### Fixed
|
||||
* XSS Vulnerability in core (https://github.com/flarum/framework/pull/3684).
|
||||
|
||||
## [v1.6.1](https://github.com/flarum/framework/compare/v1.6.0...v1.6.1)
|
||||
### Fixed
|
||||
* JS dependencies update breaks utilities.
|
||||
|
||||
## [v1.6.0](https://github.com/flarum/framework/compare/v1.5.0...v1.6.0)
|
||||
### Fixed
|
||||
- (approval) posts approved for deleted users error ([b5874a0](b5874a08e482196f50af50aa78e43c93c29fb647))
|
||||
- (regression) bad import ([5f2d7fb](5f2d7fb7b6e430d40cf2bb05eca7c73f6ca5a2cc))
|
||||
- akismet fails when the extension is not on a version ([45d9121](45d91212f6bfa777cae9fc06c55c85d01ffd174d))
|
||||
- apply flex for AppearancePage colors input [#3651]
|
||||
- groupmentions have poor contrast on some backgrounds [#3672]
|
||||
- larastan v1 incompatible with phpstan v1.9.0 [#3665]
|
||||
- package manager failures not showing alerts [#3647]
|
||||
- password reset leaks user existence [#3616]
|
||||
- statistics previous period chart is unclear [#3654]
|
||||
### Changed
|
||||
- (package-manager) config composer to use web php version ([fd19645](fd196454a5641776784fa80886cc7577c840f8ed))
|
||||
- (package-manager) set min core version and add warning ([31c3cfc](31c3cfc4eab4c314260b9b0d11e53ac2d4be158d))
|
||||
- (statistics) prepare v1.5.1 ([dc215ab](dc215aba59145dfd7b0d6efad4388444f30e47fb))
|
||||
- Apply fixes from StyleCI ([267f675](267f6759f80bd06f468337245ea6045635e827d9))
|
||||
- Fix tag discussion count decreased by 2 when hiding before deleting [#3660]
|
||||
- Log migration path when up/down keys are missing [#3664]
|
||||
- Make it possible to extend SetupScript [#3643]
|
||||
- Setup PHPStan Level 5 [#3553]
|
||||
- `yarn format` ([c5c312d](c5c312db0d800e3b84b94a4abb9691e348dea742))
|
||||
- add missing last period to custom date ranges [#3661]
|
||||
- add priorities to profile settings page [#3657]
|
||||
- allow specifying php extensions in workflow ([b0b47a0](b0b47a0888f513a459b67e9f89e72a61de38f1ce))
|
||||
- format js ([06963df](06963df4079373fc8fc51b7479e9576f02beb098))
|
||||
- group mentions [#3658]
|
||||
- remove styleci from changelog ([b2fa28e](b2fa28e4b57094e46dbdb3d79fab74f290a17d17))
|
||||
- set flarum version to dev for 1.6.0 ([fc743ba](fc743ba88872031db13597d7365a063b8004c78f))
|
||||
- throw an exception when no serializer is provided to the controller [#3614]
|
||||
### Added
|
||||
- (statistics) support for custom date ranges [#3622]
|
||||
- Allow additional login params, Introduce `LogInValidator` [#3670]
|
||||
- Allow additional reset password params, introduce `ForgotPasswordValidator` [#3671]
|
||||
- add statistics chart export button [#3662]
|
||||
- allow specifying extensions when installing an instance [#3655]
|
||||
- contrast util with yiq calculator [#3652]
|
||||
- customizable session driver [#3610]
|
||||
- replace `ColorPreviewInput` for GroupModal color input [#3650]
|
||||
- send notifications of a new reply when post is approved [#3656]
|
||||
|
||||
## [v1.5.0](https://github.com/flarum/framework/compare/v1.4.0...v1.5.0)
|
||||
### Fixed
|
||||
- (a11y) add accessible labels to notification grid options [#3520]
|
||||
@@ -38,7 +93,6 @@
|
||||
- (statistics) split timed data into per-model XHR requests [#3601]
|
||||
- (tags) Replace event helper with event dispatcher [#3570]
|
||||
- Add `loading="lazy"` attribute for avatars [#3578]
|
||||
- Apply fixes from StyleCI ([bb64114](bb641144b6bc5c59798351459fbf8df8cbf6aec6))
|
||||
- Create CODEOWNERS ([6e48a03](6e48a0303e45bcf210e550ba3e0772bc8443a207))
|
||||
- MyISAM tables for extensions during installation" ([f128190](f128190f143398dd1262fd1379e634794daee4c1))
|
||||
- convert `AlertManager` `IndexPage` and `UserPage` components to TS [#3536]
|
||||
|
@@ -84,8 +84,8 @@
|
||||
"flarum/testing": "self.version"
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": ">=7.3",
|
||||
"ext-json": "*",
|
||||
"components/font-awesome": "^5.14.0",
|
||||
"composer/composer": "^2.0",
|
||||
"dflydev/fig-cookies": "^3.0.0",
|
||||
@@ -110,8 +110,9 @@
|
||||
"illuminate/validation": "^8.0",
|
||||
"illuminate/view": "^8.0",
|
||||
"intervention/image": "2.5.* || ^2.6.1",
|
||||
"jenssegers/agent": "^2.6",
|
||||
"laminas/laminas-diactoros": "^2.4.1",
|
||||
"laminas/laminas-httphandlerrunner": "^1.2.0",
|
||||
"laminas/laminas-httphandlerrunner": "^1.2.0 || ^2.3.0",
|
||||
"laminas/laminas-stratigility": "^3.2.2",
|
||||
"league/flysystem": "^1.0.11",
|
||||
"matthiasmullie/minify": "^1.3",
|
||||
@@ -140,8 +141,8 @@
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.4",
|
||||
"phpunit/phpunit": "^9.0",
|
||||
"phpstan/phpstan-php-parser": "^1.0",
|
||||
"phpstan/phpstan": "^1.2"
|
||||
"phpstan/phpstan": ">=1.8.11 < 1.9.0",
|
||||
"nunomaduro/larastan": "^1.0"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
@@ -178,5 +179,12 @@
|
||||
"extension.neon"
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"analyse:phpstan": "phpstan analyse",
|
||||
"clear-cache:phpstan": "phpstan clear-result-cache"
|
||||
},
|
||||
"scripts-descriptions": {
|
||||
"analyse:phpstan": "Run static analysis"
|
||||
}
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.5",
|
||||
"flarum/core": "^1.6",
|
||||
"flarum/approval": "^1.2"
|
||||
},
|
||||
"autoload": {
|
||||
|
@@ -13,6 +13,7 @@ use Flarum\Approval\Event\PostWasApproved;
|
||||
use Flarum\Extend;
|
||||
use Flarum\Post\Event\Hidden;
|
||||
use Flarum\Post\Event\Saving;
|
||||
use Flarum\Post\Post;
|
||||
|
||||
return [
|
||||
(new Extend\Frontend('forum'))
|
||||
@@ -30,4 +31,7 @@ return [
|
||||
|
||||
(new Extend\ServiceProvider())
|
||||
->register(AkismetProvider::class),
|
||||
|
||||
(new Extend\Model(Post::class))
|
||||
->cast('is_spam', 'bool'),
|
||||
];
|
||||
|
2
extensions/akismet/js/dist/admin.js.map
generated
vendored
2
extensions/akismet/js/dist/admin.js.map
generated
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,IACzBH,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,kBAAkB,WACrCA,IAAAA,cAAAA,IACO,kBACJC,gBAAgB,CACfC,QAAS,yBACTC,KAAM,OACNC,MAAOJ,IAAAA,WAAAA,MAAqB,yDAE7BC,gBAAgB,CAEfC,QAAS,qCACTC,KAAM,UACNC,MAAOJ,IAAAA,WAAAA,MAAqB,mEAC5BK,KAAML,IAAAA,WAAAA,MAAqB,oEAE5BM,mBACC,CACEC,KAAM,kBACNH,MAAOJ,IAAAA,WAAAA,MAAqB,mDAC5BQ,WAAY,iBAEd,QAEL,G","sources":["webpack://@flarum/akismet/webpack/bootstrap","webpack://@flarum/akismet/webpack/runtime/compat get default export","webpack://@flarum/akismet/webpack/runtime/define property getters","webpack://@flarum/akismet/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/akismet/webpack/runtime/make namespace object","webpack://@flarum/akismet/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/akismet/./src/admin/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-akismet', () => {\n app.extensionData\n .for('flarum-akismet')\n .registerSetting({\n setting: 'flarum-akismet.api_key',\n type: 'text',\n label: app.translator.trans('flarum-akismet.admin.akismet_settings.api_key_label'),\n })\n .registerSetting({\n //https://blog.akismet.com/2014/04/23/theres-a-ninja-in-your-akismet/\n setting: 'flarum-akismet.delete_blatant_spam',\n type: 'boolean',\n label: app.translator.trans('flarum-akismet.admin.akismet_settings.delete_blatant_spam_label'),\n help: app.translator.trans('flarum-akismet.admin.akismet_settings.delete_blatant_spam_help'),\n })\n .registerPermission(\n {\n icon: 'fas fa-vote-yea',\n label: app.translator.trans('flarum-akismet.admin.permissions.bypass_akismet'),\n permission: 'bypassAkismet',\n },\n 'start'\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerSetting","setting","type","label","help","registerPermission","icon","permission"],"sourceRoot":""}
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,IACzBH,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,kBAAkB,WACrCA,IAAAA,cAAAA,IACO,kBACJC,gBAAgB,CACfC,QAAS,yBACTC,KAAM,OACNC,MAAOJ,IAAAA,WAAAA,MAAqB,yDAE7BC,gBAAgB,CAEfC,QAAS,qCACTC,KAAM,UACNC,MAAOJ,IAAAA,WAAAA,MAAqB,mEAC5BK,KAAML,IAAAA,WAAAA,MAAqB,oEAE5BM,mBACC,CACEC,KAAM,kBACNH,MAAOJ,IAAAA,WAAAA,MAAqB,mDAC5BQ,WAAY,iBAEd,QAEN,G","sources":["webpack://@flarum/akismet/webpack/bootstrap","webpack://@flarum/akismet/webpack/runtime/compat get default export","webpack://@flarum/akismet/webpack/runtime/define property getters","webpack://@flarum/akismet/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/akismet/webpack/runtime/make namespace object","webpack://@flarum/akismet/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/akismet/./src/admin/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-akismet', () => {\n app.extensionData\n .for('flarum-akismet')\n .registerSetting({\n setting: 'flarum-akismet.api_key',\n type: 'text',\n label: app.translator.trans('flarum-akismet.admin.akismet_settings.api_key_label'),\n })\n .registerSetting({\n //https://blog.akismet.com/2014/04/23/theres-a-ninja-in-your-akismet/\n setting: 'flarum-akismet.delete_blatant_spam',\n type: 'boolean',\n label: app.translator.trans('flarum-akismet.admin.akismet_settings.delete_blatant_spam_label'),\n help: app.translator.trans('flarum-akismet.admin.akismet_settings.delete_blatant_spam_help'),\n })\n .registerPermission(\n {\n icon: 'fas fa-vote-yea',\n label: app.translator.trans('flarum-akismet.admin.permissions.bypass_akismet'),\n permission: 'bypassAkismet',\n },\n 'start'\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerSetting","setting","type","label","help","registerPermission","icon","permission"],"sourceRoot":""}
|
2
extensions/akismet/js/dist/forum.js.map
generated
vendored
2
extensions/akismet/js/dist/forum.js.map
generated
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"forum.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,iBCAlD,EAA+BF,OAAOC,KAAKC,OAAO,a,aCAxD,MAAM,EAA+BF,OAAOC,KAAKC,OAAO,4B,aCAxD,MAAM,EAA+BF,OAAOC,KAAKC,OAAO,gC,aCSxDC,IAAAA,aAAAA,IAAqB,kBAAkB,YACrCC,EAAAA,EAAAA,QAAOC,IAAc,uBAAuB,SAAUC,EAAmCC,GACvF,GAAID,EAAME,IAAI,WAAY,CACxB,IAAMC,EAAQF,EAAKE,QAEnB,GAAIA,GAASA,EAAMC,MAAK,SAACC,GAAD,MAA2B,aAAb,MAAJA,OAAA,EAAAA,EAAMC,OAAhB,IAAuC,CAC7D,IAAMC,EAAcP,EAAMf,IAAI,WAC1BsB,GAAsC,iBAAhBA,GAA4B,aAAcA,IAClEA,EAAYC,SAAWX,IAAAA,WAAAA,MAAqB,6CAE/C,CACF,CACF,KAEDY,EAAAA,EAAAA,UAASC,IAAAA,UAAuB,cAAc,SAAUC,EAAUN,GAChE,MAAoB,YAAhBA,EAAKC,OACAT,IAAAA,WAAAA,MAAqB,kDAGvBc,EAASN,EACjB,GACF,G","sources":["webpack://@flarum/akismet/webpack/bootstrap","webpack://@flarum/akismet/webpack/runtime/compat get default export","webpack://@flarum/akismet/webpack/runtime/define property getters","webpack://@flarum/akismet/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/akismet/webpack/runtime/make namespace object","webpack://@flarum/akismet/external root \"flarum.core.compat['common/extend']\"","webpack://@flarum/akismet/external root \"flarum.core.compat['forum/app']\"","webpack://@flarum/akismet/external root \"flarum.core.compat['forum/utils/PostControls']\"","webpack://@flarum/akismet/external root \"flarum.core.compat['forum/components/CommentPost']\"","webpack://@flarum/akismet/./src/forum/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/extend'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['forum/app'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['forum/utils/PostControls'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['forum/components/CommentPost'];","import { extend, override } from 'flarum/common/extend';\nimport app from 'flarum/forum/app';\nimport type Post from 'flarum/common/models/Post';\nimport type ItemList from 'flarum/common/utils/ItemList';\n\nimport PostControls from 'flarum/forum/utils/PostControls';\nimport CommentPost from 'flarum/forum/components/CommentPost';\nimport type Mithril from 'mithril';\n\napp.initializers.add('flarum-akismet', () => {\n extend(PostControls, 'destructiveControls', function (items: ItemList<Mithril.Children>, post: Post) {\n if (items.has('approve')) {\n const flags = post.flags();\n\n if (flags && flags.some((flag) => flag?.type() === 'akismet')) {\n const approveItem = items.get('approve');\n if (approveItem && typeof approveItem === 'object' && 'children' in approveItem) {\n approveItem.children = app.translator.trans('flarum-akismet.forum.post.not_spam_button');\n }\n }\n }\n });\n\n override(CommentPost.prototype, 'flagReason', function (original, flag) {\n if (flag.type() === 'akismet') {\n return app.translator.trans('flarum-akismet.forum.post.akismet_flagged_text');\n }\n\n return original(flag);\n });\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","extend","PostControls","items","post","has","flags","some","flag","type","approveItem","children","override","CommentPost","original"],"sourceRoot":""}
|
||||
{"version":3,"file":"forum.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,iBCAlD,EAA+BF,OAAOC,KAAKC,OAAO,a,aCAxD,MAAM,EAA+BF,OAAOC,KAAKC,OAAO,4B,aCAxD,MAAM,EAA+BF,OAAOC,KAAKC,OAAO,gC,aCSxDC,IAAAA,aAAAA,IAAqB,kBAAkB,YACrCC,EAAAA,EAAAA,QAAOC,IAAc,uBAAuB,SAAUC,EAAmCC,GACvF,GAAID,EAAME,IAAI,WAAY,CACxB,IAAMC,EAAQF,EAAKE,QAEnB,GAAIA,GAASA,EAAMC,MAAK,SAACC,GAAI,MAAsB,aAAb,MAAJA,OAAI,EAAJA,EAAMC,OAAoB,IAAG,CAC7D,IAAMC,EAAcP,EAAMf,IAAI,WAC1BsB,GAAsC,iBAAhBA,GAA4B,aAAcA,IAClEA,EAAYC,SAAWX,IAAAA,WAAAA,MAAqB,6CAEhD,CACF,CACF,KAEAY,EAAAA,EAAAA,UAASC,IAAAA,UAAuB,cAAc,SAAUC,EAAUN,GAChE,MAAoB,YAAhBA,EAAKC,OACAT,IAAAA,WAAAA,MAAqB,kDAGvBc,EAASN,EAClB,GACF,G","sources":["webpack://@flarum/akismet/webpack/bootstrap","webpack://@flarum/akismet/webpack/runtime/compat get default export","webpack://@flarum/akismet/webpack/runtime/define property getters","webpack://@flarum/akismet/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/akismet/webpack/runtime/make namespace object","webpack://@flarum/akismet/external root \"flarum.core.compat['common/extend']\"","webpack://@flarum/akismet/external root \"flarum.core.compat['forum/app']\"","webpack://@flarum/akismet/external root \"flarum.core.compat['forum/utils/PostControls']\"","webpack://@flarum/akismet/external root \"flarum.core.compat['forum/components/CommentPost']\"","webpack://@flarum/akismet/./src/forum/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/extend'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['forum/app'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['forum/utils/PostControls'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['forum/components/CommentPost'];","import { extend, override } from 'flarum/common/extend';\nimport app from 'flarum/forum/app';\nimport type Post from 'flarum/common/models/Post';\nimport type ItemList from 'flarum/common/utils/ItemList';\n\nimport PostControls from 'flarum/forum/utils/PostControls';\nimport CommentPost from 'flarum/forum/components/CommentPost';\nimport type Mithril from 'mithril';\n\napp.initializers.add('flarum-akismet', () => {\n extend(PostControls, 'destructiveControls', function (items: ItemList<Mithril.Children>, post: Post) {\n if (items.has('approve')) {\n const flags = post.flags();\n\n if (flags && flags.some((flag) => flag?.type() === 'akismet')) {\n const approveItem = items.get('approve');\n if (approveItem && typeof approveItem === 'object' && 'children' in approveItem) {\n approveItem.children = app.translator.trans('flarum-akismet.forum.post.not_spam_button');\n }\n }\n }\n });\n\n override(CommentPost.prototype, 'flagReason', function (original, flag) {\n if (flag.type() === 'akismet') {\n return app.translator.trans('flarum-akismet.forum.post.akismet_flagged_text');\n }\n\n return original(flag);\n });\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","extend","PostControls","items","post","has","flags","some","flag","type","approveItem","children","override","CommentPost","original"],"sourceRoot":""}
|
@@ -50,7 +50,7 @@ class ValidatePost
|
||||
->withContent($post->content)
|
||||
->withAuthorName($post->user->username)
|
||||
->withAuthorEmail($post->user->email)
|
||||
->withType($post->number == 1 ? 'forum-post' : 'reply')
|
||||
->withType($post->number === 1 ? 'forum-post' : 'reply')
|
||||
->withIp($post->ip_address)
|
||||
->withUserAgent($_SERVER['HTTP_USER_AGENT'])
|
||||
->checkSpam();
|
||||
|
@@ -38,7 +38,7 @@ class AkismetProvider extends AbstractServiceProvider
|
||||
$settings->get('flarum-akismet.api_key'),
|
||||
$url->to('forum')->base(),
|
||||
$app::VERSION,
|
||||
$extensions->getExtension('flarum-akismet')->getVersion(),
|
||||
$extensions->getExtension('flarum-akismet')->getVersion() ?? 'unknown',
|
||||
$config->inDebugMode()
|
||||
);
|
||||
});
|
||||
|
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.5",
|
||||
"flarum/core": "^1.6",
|
||||
"flarum/flags": "^1.2"
|
||||
},
|
||||
"autoload": {
|
||||
|
@@ -10,6 +10,7 @@
|
||||
use Flarum\Api\Serializer\BasicDiscussionSerializer;
|
||||
use Flarum\Api\Serializer\PostSerializer;
|
||||
use Flarum\Approval\Access;
|
||||
use Flarum\Approval\Event\PostWasApproved;
|
||||
use Flarum\Approval\Listener;
|
||||
use Flarum\Discussion\Discussion;
|
||||
use Flarum\Extend;
|
||||
@@ -27,15 +28,17 @@ return [
|
||||
|
||||
// Discussions should be approved by default
|
||||
(new Extend\Model(Discussion::class))
|
||||
->default('is_approved', true),
|
||||
->default('is_approved', true)
|
||||
->cast('is_approved', 'bool'),
|
||||
|
||||
// Posts should be approved by default
|
||||
(new Extend\Model(Post::class))
|
||||
->default('is_approved', true),
|
||||
->default('is_approved', true)
|
||||
->cast('is_approved', 'bool'),
|
||||
|
||||
(new Extend\ApiSerializer(BasicDiscussionSerializer::class))
|
||||
->attribute('isApproved', function ($serializer, Discussion $discussion) {
|
||||
return (bool) $discussion->is_approved;
|
||||
return $discussion->is_approved;
|
||||
}),
|
||||
|
||||
(new Extend\ApiSerializer(PostSerializer::class))
|
||||
@@ -48,6 +51,7 @@ return [
|
||||
new Extend\Locales(__DIR__.'/locale'),
|
||||
|
||||
(new Extend\Event())
|
||||
->listen(PostWasApproved::class, Listener\UpdateDiscussionAfterPostApproval::class)
|
||||
->subscribe(Listener\ApproveContent::class)
|
||||
->subscribe(Listener\UnapproveNewContent::class),
|
||||
|
||||
|
2
extensions/approval/js/dist/admin.js.map
generated
vendored
2
extensions/approval/js/dist/admin.js.map
generated
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,iBCAlD,EAA+BF,OAAOC,KAAKC,OAAO,a,aCGxDC,IAAAA,aAAAA,IAAqB,mBAAmB,YACtCC,EAAAA,EAAAA,QAAOD,IAAK,0BAA0B,SAAUE,EAAUC,GACrC,oCAAfA,GACFD,EAASE,KAAK,mBAEG,oCAAfD,GACFD,EAASE,KAAK,mBAEjB,IAEDJ,IAAAA,cAAAA,IACO,mBACJK,mBACC,CACEC,KAAM,eACNC,MAAOP,IAAAA,WAAAA,MAAqB,8EAC5BG,WAAY,mCAEd,QACA,IAEDE,mBACC,CACEC,KAAM,eACNC,MAAOP,IAAAA,WAAAA,MAAqB,kEAC5BG,WAAY,mCAEd,QACA,IAEDE,mBACC,CACEC,KAAM,eACNC,MAAOP,IAAAA,WAAAA,MAAqB,yDAC5BG,WAAY,2BAEd,WACA,GAEL,G","sources":["webpack://@flarum/approval/webpack/bootstrap","webpack://@flarum/approval/webpack/runtime/compat get default export","webpack://@flarum/approval/webpack/runtime/define property getters","webpack://@flarum/approval/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/approval/webpack/runtime/make namespace object","webpack://@flarum/approval/external root \"flarum.core.compat['common/extend']\"","webpack://@flarum/approval/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/approval/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/extend'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import { extend } from 'flarum/common/extend';\nimport app from 'flarum/admin/app';\n\napp.initializers.add('flarum-approval', () => {\n extend(app, 'getRequiredPermissions', function (required, permission) {\n if (permission === 'discussion.startWithoutApproval') {\n required.push('startDiscussion');\n }\n if (permission === 'discussion.replyWithoutApproval') {\n required.push('discussion.reply');\n }\n });\n\n app.extensionData\n .for('flarum-approval')\n .registerPermission(\n {\n icon: 'fas fa-check',\n label: app.translator.trans('flarum-approval.admin.permissions.start_discussions_without_approval_label'),\n permission: 'discussion.startWithoutApproval',\n },\n 'start',\n 95\n )\n .registerPermission(\n {\n icon: 'fas fa-check',\n label: app.translator.trans('flarum-approval.admin.permissions.reply_without_approval_label'),\n permission: 'discussion.replyWithoutApproval',\n },\n 'reply',\n 95\n )\n .registerPermission(\n {\n icon: 'fas fa-check',\n label: app.translator.trans('flarum-approval.admin.permissions.approve_posts_label'),\n permission: 'discussion.approvePosts',\n },\n 'moderate',\n 65\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","extend","required","permission","push","registerPermission","icon","label"],"sourceRoot":""}
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,iBCAlD,EAA+BF,OAAOC,KAAKC,OAAO,a,aCGxDC,IAAAA,aAAAA,IAAqB,mBAAmB,YACtCC,EAAAA,EAAAA,QAAOD,IAAK,0BAA0B,SAAUE,EAAUC,GACrC,oCAAfA,GACFD,EAASE,KAAK,mBAEG,oCAAfD,GACFD,EAASE,KAAK,mBAElB,IAEAJ,IAAAA,cAAAA,IACO,mBACJK,mBACC,CACEC,KAAM,eACNC,MAAOP,IAAAA,WAAAA,MAAqB,8EAC5BG,WAAY,mCAEd,QACA,IAEDE,mBACC,CACEC,KAAM,eACNC,MAAOP,IAAAA,WAAAA,MAAqB,kEAC5BG,WAAY,mCAEd,QACA,IAEDE,mBACC,CACEC,KAAM,eACNC,MAAOP,IAAAA,WAAAA,MAAqB,yDAC5BG,WAAY,2BAEd,WACA,GAEN,G","sources":["webpack://@flarum/approval/webpack/bootstrap","webpack://@flarum/approval/webpack/runtime/compat get default export","webpack://@flarum/approval/webpack/runtime/define property getters","webpack://@flarum/approval/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/approval/webpack/runtime/make namespace object","webpack://@flarum/approval/external root \"flarum.core.compat['common/extend']\"","webpack://@flarum/approval/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/approval/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/extend'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import { extend } from 'flarum/common/extend';\nimport app from 'flarum/admin/app';\n\napp.initializers.add('flarum-approval', () => {\n extend(app, 'getRequiredPermissions', function (required, permission) {\n if (permission === 'discussion.startWithoutApproval') {\n required.push('startDiscussion');\n }\n if (permission === 'discussion.replyWithoutApproval') {\n required.push('discussion.reply');\n }\n });\n\n app.extensionData\n .for('flarum-approval')\n .registerPermission(\n {\n icon: 'fas fa-check',\n label: app.translator.trans('flarum-approval.admin.permissions.start_discussions_without_approval_label'),\n permission: 'discussion.startWithoutApproval',\n },\n 'start',\n 95\n )\n .registerPermission(\n {\n icon: 'fas fa-check',\n label: app.translator.trans('flarum-approval.admin.permissions.reply_without_approval_label'),\n permission: 'discussion.replyWithoutApproval',\n },\n 'reply',\n 95\n )\n .registerPermission(\n {\n icon: 'fas fa-check',\n label: app.translator.trans('flarum-approval.admin.permissions.approve_posts_label'),\n permission: 'discussion.approvePosts',\n },\n 'moderate',\n 65\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","extend","required","permission","push","registerPermission","icon","label"],"sourceRoot":""}
|
2
extensions/approval/js/dist/forum.js.map
generated
vendored
2
extensions/approval/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -21,12 +21,8 @@ class ApproveContent
|
||||
public function subscribe(Dispatcher $events)
|
||||
{
|
||||
$events->listen(Saving::class, [$this, 'approvePost']);
|
||||
$events->listen(PostWasApproved::class, [$this, 'approveDiscussion']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Saving $event
|
||||
*/
|
||||
public function approvePost(Saving $event)
|
||||
{
|
||||
$attributes = $event->data['attributes'];
|
||||
@@ -46,30 +42,4 @@ class ApproveContent
|
||||
$post->raise(new PostWasApproved($post, $event->actor));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostWasApproved $event
|
||||
*/
|
||||
public function approveDiscussion(PostWasApproved $event)
|
||||
{
|
||||
$post = $event->post;
|
||||
$discussion = $post->discussion;
|
||||
$user = $discussion->user;
|
||||
|
||||
$discussion->refreshCommentCount();
|
||||
$discussion->refreshLastPost();
|
||||
|
||||
if ($post->number == 1) {
|
||||
$discussion->is_approved = true;
|
||||
|
||||
$discussion->afterSave(function () use ($user) {
|
||||
$user->refreshDiscussionCount();
|
||||
});
|
||||
}
|
||||
|
||||
$discussion->save();
|
||||
|
||||
$user->refreshCommentCount();
|
||||
$user->save();
|
||||
}
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace Flarum\Approval\Listener;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Flarum\Discussion\Discussion;
|
||||
use Flarum\Flags\Flag;
|
||||
use Flarum\Post\CommentPost;
|
||||
@@ -55,7 +56,7 @@ class UnapproveNewContent
|
||||
|
||||
$flag->post_id = $post->id;
|
||||
$flag->type = 'approval';
|
||||
$flag->created_at = time();
|
||||
$flag->created_at = Carbon::now();
|
||||
|
||||
$flag->save();
|
||||
});
|
||||
|
@@ -0,0 +1,40 @@
|
||||
<?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\Approval\Listener;
|
||||
|
||||
use Flarum\Approval\Event\PostWasApproved;
|
||||
|
||||
class UpdateDiscussionAfterPostApproval
|
||||
{
|
||||
public function handle(PostWasApproved $event)
|
||||
{
|
||||
$post = $event->post;
|
||||
$discussion = $post->discussion;
|
||||
$user = $discussion->user;
|
||||
|
||||
$discussion->refreshCommentCount();
|
||||
$discussion->refreshLastPost();
|
||||
|
||||
if ($post->number === 1) {
|
||||
$discussion->is_approved = true;
|
||||
|
||||
$discussion->afterSave(function () use ($user) {
|
||||
$user->refreshDiscussionCount();
|
||||
});
|
||||
}
|
||||
|
||||
$discussion->save();
|
||||
|
||||
if ($discussion->user) {
|
||||
$user->refreshCommentCount();
|
||||
$user->save();
|
||||
}
|
||||
}
|
||||
}
|
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.5"
|
||||
"flarum/core": "^1.6"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
|
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.5"
|
||||
"flarum/core": "^1.6"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
2
extensions/embed/js/dist/forum.js.map
generated
vendored
2
extensions/embed/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.5"
|
||||
"flarum/core": "^1.6"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
|
2
extensions/emoji/js/dist/forum.js
generated
vendored
2
extensions/emoji/js/dist/forum.js
generated
vendored
File diff suppressed because one or more lines are too long
2
extensions/emoji/js/dist/forum.js.map
generated
vendored
2
extensions/emoji/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -3,7 +3,7 @@ import emojiMap from 'simple-emoji-map';
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import TextEditor from 'flarum/common/components/TextEditor';
|
||||
import TextEditorButton from 'flarum/common/components/TextEditorButton';
|
||||
import KeyboardNavigatable from 'flarum/forum/utils/KeyboardNavigatable';
|
||||
import KeyboardNavigatable from 'flarum/common/utils/KeyboardNavigatable';
|
||||
|
||||
import AutocompleteDropdown from './fragments/AutocompleteDropdown';
|
||||
import getEmojiIconCode from './helpers/getEmojiIconCode';
|
||||
|
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.5"
|
||||
"flarum/core": "^1.6"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@@ -46,7 +46,7 @@ return [
|
||||
->delete('/posts/{id}/flags', 'flags.delete', DeleteFlagsController::class),
|
||||
|
||||
(new Extend\Model(User::class))
|
||||
->dateAttribute('read_flags_at'),
|
||||
->cast('read_flags_at', 'datetime'),
|
||||
|
||||
(new Extend\Model(Post::class))
|
||||
->hasMany('flags', Flag::class, 'post_id'),
|
||||
|
2
extensions/flags/js/dist-typings/forum/compat.d.ts
generated
vendored
2
extensions/flags/js/dist-typings/forum/compat.d.ts
generated
vendored
@@ -1,4 +1,4 @@
|
||||
declare var _default: {
|
||||
declare const _default: {
|
||||
'flags/addFlagsToPosts': typeof addFlagsToPosts;
|
||||
'flags/addFlagControl': typeof addFlagControl;
|
||||
'flags/addFlagsDropdown': typeof addFlagsDropdown;
|
||||
|
2
extensions/flags/js/dist-typings/forum/components/FlagPostModal.d.ts
generated
vendored
2
extensions/flags/js/dist-typings/forum/components/FlagPostModal.d.ts
generated
vendored
@@ -1,5 +1,5 @@
|
||||
/// <reference types="flarum/@types/translator-icu-rich" />
|
||||
export default class FlagPostModal extends Modal<import("flarum/common/components/Modal").IInternalModalAttrs> {
|
||||
export default class FlagPostModal extends Modal<import("flarum/common/components/Modal").IInternalModalAttrs, undefined> {
|
||||
constructor();
|
||||
oninit(vnode: any): void;
|
||||
success: boolean | undefined;
|
||||
|
2
extensions/flags/js/dist-typings/forum/extend.d.ts
generated
vendored
Normal file
2
extensions/flags/js/dist-typings/forum/extend.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const _default: (import("flarum/common/extenders/Model").default | import("flarum/common/extenders/Routes").default | import("flarum/common/extenders/Store").default)[];
|
||||
export default _default;
|
2
extensions/flags/js/dist-typings/forum/index.d.ts
generated
vendored
2
extensions/flags/js/dist-typings/forum/index.d.ts
generated
vendored
@@ -1 +1 @@
|
||||
export {};
|
||||
export { default as extend } from './extend';
|
||||
|
2
extensions/flags/js/dist/admin.js.map
generated
vendored
2
extensions/flags/js/dist/admin.js.map
generated
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,gBAAgB,WACnCA,IAAAA,cAAAA,IACO,gBACJC,gBACC,CACEC,QAAS,8BACTC,KAAM,OACNC,MAAOJ,IAAAA,WAAAA,MAAqB,qDAE9B,IAEDC,gBAAgB,CACfC,QAAS,4BACTC,KAAM,UACNC,MAAOJ,IAAAA,WAAAA,MAAqB,sDAE7BK,mBACC,CACEC,KAAM,cACNF,MAAOJ,IAAAA,WAAAA,MAAqB,mDAC5BO,WAAY,wBAEd,WACA,IAGDF,mBACC,CACEC,KAAM,cACNF,MAAOJ,IAAAA,WAAAA,MAAqB,mDAC5BO,WAAY,wBAEd,QACA,GAEL,G","sources":["webpack://@flarum/flags/webpack/bootstrap","webpack://@flarum/flags/webpack/runtime/compat get default export","webpack://@flarum/flags/webpack/runtime/define property getters","webpack://@flarum/flags/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/flags/webpack/runtime/make namespace object","webpack://@flarum/flags/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/flags/./src/admin/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-flags', () => {\n app.extensionData\n .for('flarum-flags')\n .registerSetting(\n {\n setting: 'flarum-flags.guidelines_url',\n type: 'text',\n label: app.translator.trans('flarum-flags.admin.settings.guidelines_url_label'),\n },\n 15\n )\n .registerSetting({\n setting: 'flarum-flags.can_flag_own',\n type: 'boolean',\n label: app.translator.trans('flarum-flags.admin.settings.flag_own_posts_label'),\n })\n .registerPermission(\n {\n icon: 'fas fa-flag',\n label: app.translator.trans('flarum-flags.admin.permissions.view_flags_label'),\n permission: 'discussion.viewFlags',\n },\n 'moderate',\n 65\n )\n\n .registerPermission(\n {\n icon: 'fas fa-flag',\n label: app.translator.trans('flarum-flags.admin.permissions.flag_posts_label'),\n permission: 'discussion.flagPosts',\n },\n 'reply',\n 65\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerSetting","setting","type","label","registerPermission","icon","permission"],"sourceRoot":""}
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,gBAAgB,WACnCA,IAAAA,cAAAA,IACO,gBACJC,gBACC,CACEC,QAAS,8BACTC,KAAM,OACNC,MAAOJ,IAAAA,WAAAA,MAAqB,qDAE9B,IAEDC,gBAAgB,CACfC,QAAS,4BACTC,KAAM,UACNC,MAAOJ,IAAAA,WAAAA,MAAqB,sDAE7BK,mBACC,CACEC,KAAM,cACNF,MAAOJ,IAAAA,WAAAA,MAAqB,mDAC5BO,WAAY,wBAEd,WACA,IAGDF,mBACC,CACEC,KAAM,cACNF,MAAOJ,IAAAA,WAAAA,MAAqB,mDAC5BO,WAAY,wBAEd,QACA,GAEN,G","sources":["webpack://@flarum/flags/webpack/bootstrap","webpack://@flarum/flags/webpack/runtime/compat get default export","webpack://@flarum/flags/webpack/runtime/define property getters","webpack://@flarum/flags/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/flags/webpack/runtime/make namespace object","webpack://@flarum/flags/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/flags/./src/admin/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-flags', () => {\n app.extensionData\n .for('flarum-flags')\n .registerSetting(\n {\n setting: 'flarum-flags.guidelines_url',\n type: 'text',\n label: app.translator.trans('flarum-flags.admin.settings.guidelines_url_label'),\n },\n 15\n )\n .registerSetting({\n setting: 'flarum-flags.can_flag_own',\n type: 'boolean',\n label: app.translator.trans('flarum-flags.admin.settings.flag_own_posts_label'),\n })\n .registerPermission(\n {\n icon: 'fas fa-flag',\n label: app.translator.trans('flarum-flags.admin.permissions.view_flags_label'),\n permission: 'discussion.viewFlags',\n },\n 'moderate',\n 65\n )\n\n .registerPermission(\n {\n icon: 'fas fa-flag',\n label: app.translator.trans('flarum-flags.admin.permissions.flag_posts_label'),\n permission: 'discussion.flagPosts',\n },\n 'reply',\n 65\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerSetting","setting","type","label","registerPermission","icon","permission"],"sourceRoot":""}
|
2
extensions/flags/js/dist/forum.js
generated
vendored
2
extensions/flags/js/dist/forum.js
generated
vendored
File diff suppressed because one or more lines are too long
2
extensions/flags/js/dist/forum.js.map
generated
vendored
2
extensions/flags/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
16
extensions/flags/js/src/forum/extend.ts
Normal file
16
extensions/flags/js/src/forum/extend.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import Extend from 'flarum/common/extenders';
|
||||
import Post from 'flarum/common/models/Post';
|
||||
import FlagsPage from './components/FlagsPage';
|
||||
import Flag from './models/Flag';
|
||||
|
||||
export default [
|
||||
new Extend.Routes() //
|
||||
.add('flags', '/flags', FlagsPage),
|
||||
|
||||
new Extend.Store() //
|
||||
.add('flags', Flag),
|
||||
|
||||
new Extend.Model(Post) //
|
||||
.hasMany<Flag>('flags')
|
||||
.attribute<boolean>('canFlag'),
|
||||
];
|
@@ -1,21 +1,13 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import Model from 'flarum/common/Model';
|
||||
|
||||
import Flag from './models/Flag';
|
||||
import FlagsPage from './components/FlagsPage';
|
||||
import FlagListState from './states/FlagListState';
|
||||
import addFlagControl from './addFlagControl';
|
||||
import addFlagsDropdown from './addFlagsDropdown';
|
||||
import addFlagsToPosts from './addFlagsToPosts';
|
||||
|
||||
export { default as extend } from './extend';
|
||||
|
||||
app.initializers.add('flarum-flags', () => {
|
||||
Post.prototype.flags = Model.hasMany<Flag>('flags');
|
||||
Post.prototype.canFlag = Model.attribute<boolean>('canFlag');
|
||||
|
||||
app.store.models.flags = Flag;
|
||||
|
||||
app.routes.flags = { path: '/flags', component: FlagsPage };
|
||||
|
||||
app.flags = new FlagListState(app);
|
||||
|
||||
addFlagControl();
|
||||
@@ -26,6 +18,5 @@ app.initializers.add('flarum-flags', () => {
|
||||
// Expose compat API
|
||||
import flagsCompat from './compat';
|
||||
import { compat } from '@flarum/core/forum';
|
||||
import Post from 'flarum/common/models/Post';
|
||||
|
||||
Object.assign(compat, flagsCompat);
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace Flarum\Flags\Api\Controller;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Flarum\Api\Controller\AbstractListController;
|
||||
use Flarum\Flags\Api\Serializer\FlagSerializer;
|
||||
use Flarum\Flags\Flag;
|
||||
@@ -43,7 +44,7 @@ class ListFlagsController extends AbstractListController
|
||||
|
||||
$actor->assertRegistered();
|
||||
|
||||
$actor->read_flags_at = time();
|
||||
$actor->read_flags_at = Carbon::now();
|
||||
$actor->save();
|
||||
|
||||
$flags = Flag::whereVisibleTo($actor)
|
||||
|
@@ -12,6 +12,8 @@ namespace Flarum\Flags\Api\Serializer;
|
||||
use Flarum\Api\Serializer\AbstractSerializer;
|
||||
use Flarum\Api\Serializer\BasicUserSerializer;
|
||||
use Flarum\Api\Serializer\PostSerializer;
|
||||
use Flarum\Flags\Flag;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class FlagSerializer extends AbstractSerializer
|
||||
{
|
||||
@@ -20,11 +22,14 @@ class FlagSerializer extends AbstractSerializer
|
||||
*/
|
||||
protected $type = 'flags';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getDefaultAttributes($flag)
|
||||
{
|
||||
if (! ($flag instanceof Flag)) {
|
||||
throw new InvalidArgumentException(
|
||||
get_class($this).' can only serialize instances of '.Flag::class
|
||||
);
|
||||
}
|
||||
|
||||
return [
|
||||
'type' => $flag->type,
|
||||
'reason' => $flag->reason,
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace Flarum\Flags\Command;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Flarum\Flags\Event\Created;
|
||||
use Flarum\Flags\Flag;
|
||||
use Flarum\Foundation\ValidationException;
|
||||
@@ -99,7 +100,7 @@ class CreateFlagHandler
|
||||
$flag->type = 'user';
|
||||
$flag->reason = Arr::get($data, 'attributes.reason');
|
||||
$flag->reason_detail = Arr::get($data, 'attributes.reasonDetail');
|
||||
$flag->created_at = time();
|
||||
$flag->created_at = Carbon::now();
|
||||
|
||||
$flag->save();
|
||||
|
||||
|
@@ -11,7 +11,7 @@ namespace Flarum\Flags\Command;
|
||||
|
||||
use Flarum\Flags\Event\Deleting;
|
||||
use Flarum\Flags\Event\FlagsWillBeDeleted;
|
||||
use Flarum\Flags\Flag;
|
||||
use Flarum\Post\Post;
|
||||
use Flarum\Post\PostRepository;
|
||||
use Illuminate\Events\Dispatcher;
|
||||
|
||||
@@ -39,7 +39,7 @@ class DeleteFlagsHandler
|
||||
|
||||
/**
|
||||
* @param DeleteFlags $command
|
||||
* @return Flag
|
||||
* @return Post
|
||||
*/
|
||||
public function handle(DeleteFlags $command)
|
||||
{
|
||||
|
@@ -9,11 +9,23 @@
|
||||
|
||||
namespace Flarum\Flags;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Flarum\Database\AbstractModel;
|
||||
use Flarum\Database\ScopeVisibilityTrait;
|
||||
use Flarum\Post\Post;
|
||||
use Flarum\User\User;
|
||||
|
||||
/**
|
||||
* @property int $post_id
|
||||
* @property int $user_id
|
||||
* @property string $type
|
||||
* @property string $reason
|
||||
* @property string $reason_detail
|
||||
* @property Carbon $created_at
|
||||
*
|
||||
* @property-read Post $post
|
||||
* @property-read User $user
|
||||
*/
|
||||
class Flag extends AbstractModel
|
||||
{
|
||||
use ScopeVisibilityTrait;
|
||||
|
@@ -7,7 +7,7 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"flarum/core": "^1.5"
|
||||
"flarum/core": "^1.6"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
|
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.5"
|
||||
"flarum/core": "^1.6"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
2
extensions/likes/js/dist/admin.js.map
generated
vendored
2
extensions/likes/js/dist/admin.js.map
generated
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,gBAAgB,WACnCA,IAAAA,cAAAA,IACO,gBACJC,mBACC,CACEC,KAAM,mBACNC,MAAOH,IAAAA,WAAAA,MAAqB,mDAC5BI,WAAY,wBAEd,SAEDC,gBAAgB,CACfC,QAAS,6BACTC,KAAM,OACNJ,MAAOH,IAAAA,WAAAA,MAAqB,oDAC5BQ,KAAMR,IAAAA,WAAAA,MAAqB,oDAEhC,G","sources":["webpack://@flarum/likes/webpack/bootstrap","webpack://@flarum/likes/webpack/runtime/compat get default export","webpack://@flarum/likes/webpack/runtime/define property getters","webpack://@flarum/likes/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/likes/webpack/runtime/make namespace object","webpack://@flarum/likes/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/likes/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-likes', () => {\n app.extensionData\n .for('flarum-likes')\n .registerPermission(\n {\n icon: 'far fa-thumbs-up',\n label: app.translator.trans('flarum-likes.admin.permissions.like_posts_label'),\n permission: 'discussion.likePosts',\n },\n 'reply'\n )\n .registerSetting({\n setting: 'flarum-likes.like_own_post',\n type: 'bool',\n label: app.translator.trans('flarum-likes.admin.settings.like_own_posts_label'),\n help: app.translator.trans('flarum-likes.admin.settings.like_own_posts_help'),\n });\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerPermission","icon","label","permission","registerSetting","setting","type","help"],"sourceRoot":""}
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,gBAAgB,WACnCA,IAAAA,cAAAA,IACO,gBACJC,mBACC,CACEC,KAAM,mBACNC,MAAOH,IAAAA,WAAAA,MAAqB,mDAC5BI,WAAY,wBAEd,SAEDC,gBAAgB,CACfC,QAAS,6BACTC,KAAM,OACNJ,MAAOH,IAAAA,WAAAA,MAAqB,oDAC5BQ,KAAMR,IAAAA,WAAAA,MAAqB,oDAEjC,G","sources":["webpack://@flarum/likes/webpack/bootstrap","webpack://@flarum/likes/webpack/runtime/compat get default export","webpack://@flarum/likes/webpack/runtime/define property getters","webpack://@flarum/likes/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/likes/webpack/runtime/make namespace object","webpack://@flarum/likes/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/likes/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-likes', () => {\n app.extensionData\n .for('flarum-likes')\n .registerPermission(\n {\n icon: 'far fa-thumbs-up',\n label: app.translator.trans('flarum-likes.admin.permissions.like_posts_label'),\n permission: 'discussion.likePosts',\n },\n 'reply'\n )\n .registerSetting({\n setting: 'flarum-likes.like_own_post',\n type: 'bool',\n label: app.translator.trans('flarum-likes.admin.settings.like_own_posts_label'),\n help: app.translator.trans('flarum-likes.admin.settings.like_own_posts_help'),\n });\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerPermission","icon","label","permission","registerSetting","setting","type","help"],"sourceRoot":""}
|
2
extensions/likes/js/dist/forum.js
generated
vendored
2
extensions/likes/js/dist/forum.js
generated
vendored
File diff suppressed because one or more lines are too long
2
extensions/likes/js/dist/forum.js.map
generated
vendored
2
extensions/likes/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -2,17 +2,15 @@ import { extend } from 'flarum/common/extend';
|
||||
import app from 'flarum/forum/app';
|
||||
import UserPage from 'flarum/forum/components/UserPage';
|
||||
import LinkButton from 'flarum/common/components/LinkButton';
|
||||
import LikesUserPage from './components/LikesUserPage';
|
||||
import ItemList from 'flarum/common/utils/ItemList';
|
||||
import type Mithril from 'mithril';
|
||||
|
||||
export default function addLikesTabToUserProfile() {
|
||||
app.routes['user.likes'] = { path: '/u/:username/likes', component: LikesUserPage };
|
||||
extend(UserPage.prototype, 'navItems', function (items: ItemList<Mithril.Children>) {
|
||||
const user = this.user;
|
||||
items.add(
|
||||
'likes',
|
||||
<LinkButton href={app.route('user.likes', { username: user.slug() })} icon="far fa-thumbs-up">
|
||||
<LinkButton href={app.route('user.likes', { username: user?.slug() })} icon="far fa-thumbs-up">
|
||||
{app.translator.trans('flarum-likes.forum.user.likes_link')}
|
||||
</LinkButton>,
|
||||
88
|
||||
|
13
extensions/likes/js/src/forum/extend.ts
Normal file
13
extensions/likes/js/src/forum/extend.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import Extend from 'flarum/common/extenders';
|
||||
import Post from 'flarum/common/models/Post';
|
||||
import User from 'flarum/common/models/User';
|
||||
import LikesUserPage from './components/LikesUserPage';
|
||||
|
||||
export default [
|
||||
new Extend.Routes() //
|
||||
.add('user.likes', '/u/:username/likes', LikesUserPage),
|
||||
|
||||
new Extend.Model(Post) //
|
||||
.hasMany<User>('likes')
|
||||
.attribute<boolean>('canLike'),
|
||||
];
|
@@ -1,7 +1,5 @@
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import app from 'flarum/forum/app';
|
||||
import Post from 'flarum/common/models/Post';
|
||||
import Model from 'flarum/common/Model';
|
||||
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
||||
|
||||
import addLikeAction from './addLikeAction';
|
||||
@@ -9,12 +7,11 @@ import addLikesList from './addLikesList';
|
||||
import PostLikedNotification from './components/PostLikedNotification';
|
||||
import addLikesTabToUserProfile from './addLikesTabToUserProfile';
|
||||
|
||||
export { default as extend } from './extend';
|
||||
|
||||
app.initializers.add('flarum-likes', () => {
|
||||
app.notificationComponents.postLiked = PostLikedNotification;
|
||||
|
||||
Post.prototype.canLike = Model.attribute('canLike');
|
||||
Post.prototype.likes = Model.hasMany('likes');
|
||||
|
||||
addLikeAction();
|
||||
addLikesList();
|
||||
addLikesTabToUserProfile();
|
||||
|
20
extensions/likes/js/tsconfig.json
Normal file
20
extensions/likes/js/tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
// Use Flarum's tsconfig as a starting point
|
||||
"extends": "flarum-tsconfig",
|
||||
// This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder
|
||||
// and also tells your Typescript server to read core's global typings for
|
||||
// access to `dayjs` and `$` in the global namespace.
|
||||
"include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"],
|
||||
"compilerOptions": {
|
||||
// This will output typings to `dist-typings`
|
||||
"declarationDir": "./dist-typings",
|
||||
"paths": {
|
||||
"flarum/*": ["../../../framework/core/js/dist-typings/*"],
|
||||
// TODO: remove after export registry system implemented
|
||||
// Without this, the old-style `@flarum/core` import is resolved to
|
||||
// source code in flarum/core instead of the dist typings.
|
||||
// This causes an inaccurate "duplicate export" error.
|
||||
"@flarum/core/*": ["../../../framework/core/js/dist-typings/*"],
|
||||
}
|
||||
}
|
||||
}
|
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.5"
|
||||
"flarum/core": "^1.6"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@@ -35,12 +35,15 @@ return [
|
||||
(new Extend\Notification())
|
||||
->type(DiscussionLockedBlueprint::class, BasicDiscussionSerializer::class, ['alert']),
|
||||
|
||||
(new Extend\Model(Discussion::class))
|
||||
->cast('is_locked', 'bool'),
|
||||
|
||||
(new Extend\ApiSerializer(DiscussionSerializer::class))
|
||||
->attribute('isLocked', function (DiscussionSerializer $serializer, Discussion $discussion) {
|
||||
return (bool) $discussion->is_locked;
|
||||
return $discussion->is_locked;
|
||||
})
|
||||
->attribute('canLock', function (DiscussionSerializer $serializer, Discussion $discussion) {
|
||||
return (bool) $serializer->getActor()->can('lock', $discussion);
|
||||
return $serializer->getActor()->can('lock', $discussion);
|
||||
}),
|
||||
|
||||
(new Extend\Post())
|
||||
|
2
extensions/lock/js/dist/admin.js.map
generated
vendored
2
extensions/lock/js/dist/admin.js.map
generated
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,QAAQ,WAC3BA,IAAAA,cAAAA,IAAsB,eAAeC,mBACnC,CACEC,KAAM,cACNC,MAAOH,IAAAA,WAAAA,MAAqB,wDAC5BI,WAAY,mBAEd,WACA,GAEH,G","sources":["webpack://@flarum/lock/webpack/bootstrap","webpack://@flarum/lock/webpack/runtime/compat get default export","webpack://@flarum/lock/webpack/runtime/define property getters","webpack://@flarum/lock/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/lock/webpack/runtime/make namespace object","webpack://@flarum/lock/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/lock/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('lock', () => {\n app.extensionData.for('flarum-lock').registerPermission(\n {\n icon: 'fas fa-lock',\n label: app.translator.trans('flarum-lock.admin.permissions.lock_discussions_label'),\n permission: 'discussion.lock',\n },\n 'moderate',\n 95\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerPermission","icon","label","permission"],"sourceRoot":""}
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,QAAQ,WAC3BA,IAAAA,cAAAA,IAAsB,eAAeC,mBACnC,CACEC,KAAM,cACNC,MAAOH,IAAAA,WAAAA,MAAqB,wDAC5BI,WAAY,mBAEd,WACA,GAEJ,G","sources":["webpack://@flarum/lock/webpack/bootstrap","webpack://@flarum/lock/webpack/runtime/compat get default export","webpack://@flarum/lock/webpack/runtime/define property getters","webpack://@flarum/lock/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/lock/webpack/runtime/make namespace object","webpack://@flarum/lock/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/lock/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('lock', () => {\n app.extensionData.for('flarum-lock').registerPermission(\n {\n icon: 'fas fa-lock',\n label: app.translator.trans('flarum-lock.admin.permissions.lock_discussions_label'),\n permission: 'discussion.lock',\n },\n 'moderate',\n 95\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerPermission","icon","label","permission"],"sourceRoot":""}
|
2
extensions/lock/js/dist/forum.js
generated
vendored
2
extensions/lock/js/dist/forum.js
generated
vendored
@@ -1,2 +1,2 @@
|
||||
(()=>{var o={n:t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return o.d(n,{a:n}),n},d:(t,n)=>{for(var c in n)o.o(n,c)&&!o.o(t,c)&&Object.defineProperty(t,c,{enumerable:!0,get:n[c]})},o:(o,t)=>Object.prototype.hasOwnProperty.call(o,t),r:o=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(o,"__esModule",{value:!0})}},t={};(()=>{"use strict";o.r(t);const n=flarum.core.compat["common/extend"],c=flarum.core.compat["forum/app"];var r=o.n(c);const e=flarum.core.compat["common/Model"];var s=o.n(e);const a=flarum.core.compat["common/models/Discussion"];var i=o.n(a);const u=flarum.core.compat["forum/components/NotificationGrid"];var l=o.n(u);function f(o,t){return f=Object.setPrototypeOf||function(o,t){return o.__proto__=t,o},f(o,t)}function p(o,t){o.prototype=Object.create(t.prototype),o.prototype.constructor=o,f(o,t)}const d=flarum.core.compat["forum/components/EventPost"];var k=function(o){function t(){return o.apply(this,arguments)||this}p(t,o);var n=t.prototype;return n.icon=function(){return this.attrs.post.content().locked?"fas fa-lock":"fas fa-unlock"},n.descriptionKey=function(){return this.attrs.post.content().locked?"flarum-lock.forum.post_stream.discussion_locked_text":"flarum-lock.forum.post_stream.discussion_unlocked_text"},t}(o.n(d)());const y=flarum.core.compat["forum/components/Notification"];var _=function(o){function t(){return o.apply(this,arguments)||this}p(t,o);var n=t.prototype;return n.icon=function(){return"fas fa-lock"},n.href=function(){var o=this.attrs.notification;return r().route.discussion(o.subject(),o.content().postNumber)},n.content=function(){return r().translator.trans("flarum-lock.forum.notifications.discussion_locked_text",{user:this.attrs.notification.fromUser()})},t}(o.n(y)());const b=flarum.core.compat["common/components/Badge"];var v=o.n(b);const h=flarum.core.compat["forum/utils/DiscussionControls"];var L=o.n(h);const g=flarum.core.compat["forum/components/DiscussionPage"];var x=o.n(g);const O=flarum.core.compat["common/components/Button"];var j=o.n(O);r().initializers.add("flarum-lock",(function(){r().postComponents.discussionLocked=k,r().notificationComponents.discussionLocked=_,i().prototype.isLocked=s().attribute("isLocked"),i().prototype.canLock=s().attribute("canLock"),(0,n.extend)(i().prototype,"badges",(function(o){this.isLocked()&&o.add("locked",v().component({type:"locked",label:r().translator.trans("flarum-lock.forum.badge.locked_tooltip"),icon:"fas fa-lock"}))})),(0,n.extend)(L(),"moderationControls",(function(o,t){t.canLock()&&o.add("lock",j().component({icon:"fas fa-lock",onclick:this.lockAction.bind(t)},r().translator.trans(t.isLocked()?"flarum-lock.forum.discussion_controls.unlock_button":"flarum-lock.forum.discussion_controls.lock_button")))})),L().lockAction=function(){this.save({isLocked:!this.isLocked()}).then((function(){r().current.matches(x())&&r().current.get("stream").update(),m.redraw()}))},(0,n.extend)(l().prototype,"notificationTypes",(function(o){o.add("discussionLocked",{name:"discussionLocked",icon:"fas fa-lock",label:r().translator.trans("flarum-lock.forum.settings.notify_discussion_locked_label")})}))}))})(),module.exports=t})();
|
||||
(()=>{var o={n:t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return o.d(n,{a:n}),n},d:(t,n)=>{for(var e in n)o.o(n,e)&&!o.o(t,e)&&Object.defineProperty(t,e,{enumerable:!0,get:n[e]})},o:(o,t)=>Object.prototype.hasOwnProperty.call(o,t),r:o=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(o,"__esModule",{value:!0})}},t={};(()=>{"use strict";o.r(t),o.d(t,{extend:()=>j});const n=flarum.core.compat["common/extend"],e=flarum.core.compat["forum/app"];var c=o.n(e);const r=flarum.core.compat["forum/components/NotificationGrid"];var s=o.n(r);function a(o,t){return a=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(o,t){return o.__proto__=t,o},a(o,t)}function i(o,t){o.prototype=Object.create(t.prototype),o.prototype.constructor=o,a(o,t)}const u=flarum.core.compat["forum/components/Notification"];var l=function(o){function t(){return o.apply(this,arguments)||this}i(t,o);var n=t.prototype;return n.icon=function(){return"fas fa-lock"},n.href=function(){var o=this.attrs.notification;return c().route.discussion(o.subject(),o.content().postNumber)},n.content=function(){return c().translator.trans("flarum-lock.forum.notifications.discussion_locked_text",{user:this.attrs.notification.fromUser()})},t}(o.n(u)());const f=flarum.core.compat["common/models/Discussion"];var d=o.n(f);const p=flarum.core.compat["common/components/Badge"];var k=o.n(p);const y=flarum.core.compat["forum/utils/DiscussionControls"];var b=o.n(y);const _=flarum.core.compat["forum/components/DiscussionPage"];var v=o.n(_);const h=flarum.core.compat["common/components/Button"];var g=o.n(h);const L=flarum.core.compat["common/extenders"];var x=o.n(L);const O=flarum.core.compat["forum/components/EventPost"];var P=function(o){function t(){return o.apply(this,arguments)||this}i(t,o);var n=t.prototype;return n.icon=function(){return this.attrs.post.content().locked?"fas fa-lock":"fas fa-unlock"},n.descriptionKey=function(){return this.attrs.post.content().locked?"flarum-lock.forum.post_stream.discussion_locked_text":"flarum-lock.forum.post_stream.discussion_unlocked_text"},t}(o.n(O)());const j=[(new(x().PostTypes)).add("discussionLocked",P),new(x().Model)(d()).attribute("isLocked").attribute("canLock")];c().initializers.add("flarum-lock",(function(){c().notificationComponents.discussionLocked=l,(0,n.extend)(d().prototype,"badges",(function(o){this.isLocked()&&o.add("locked",k().component({type:"locked",label:c().translator.trans("flarum-lock.forum.badge.locked_tooltip"),icon:"fas fa-lock"}))})),(0,n.extend)(b(),"moderationControls",(function(o,t){t.canLock()&&o.add("lock",g().component({icon:"fas fa-lock",onclick:this.lockAction.bind(t)},c().translator.trans(t.isLocked()?"flarum-lock.forum.discussion_controls.unlock_button":"flarum-lock.forum.discussion_controls.lock_button")))})),b().lockAction=function(){this.save({isLocked:!this.isLocked()}).then((function(){c().current.matches(v())&&c().current.get("stream").update(),m.redraw()}))},(0,n.extend)(s().prototype,"notificationTypes",(function(o){o.add("discussionLocked",{name:"discussionLocked",icon:"fas fa-lock",label:c().translator.trans("flarum-lock.forum.settings.notify_discussion_locked_label")})}))}))})(),module.exports=t})();
|
||||
//# sourceMappingURL=forum.js.map
|
2
extensions/lock/js/dist/forum.js.map
generated
vendored
2
extensions/lock/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
12
extensions/lock/js/src/forum/extend.ts
Normal file
12
extensions/lock/js/src/forum/extend.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import Extend from 'flarum/common/extenders';
|
||||
import Discussion from 'flarum/common/models/Discussion';
|
||||
import DiscussionLockedPost from './components/DiscussionLockedPost';
|
||||
|
||||
export default [
|
||||
new Extend.PostTypes() //
|
||||
.add('discussionLocked', DiscussionLockedPost),
|
||||
|
||||
new Extend.Model(Discussion) //
|
||||
.attribute<boolean>('isLocked')
|
||||
.attribute<boolean>('canLock'),
|
||||
];
|
@@ -1,20 +1,15 @@
|
||||
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 NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
||||
|
||||
import DiscussionLockedPost from './components/DiscussionLockedPost';
|
||||
import DiscussionLockedNotification from './components/DiscussionLockedNotification';
|
||||
import addLockBadge from './addLockBadge';
|
||||
import addLockControl from './addLockControl';
|
||||
|
||||
app.initializers.add('flarum-lock', () => {
|
||||
app.postComponents.discussionLocked = DiscussionLockedPost;
|
||||
app.notificationComponents.discussionLocked = DiscussionLockedNotification;
|
||||
export { default as extend } from './extend';
|
||||
|
||||
Discussion.prototype.isLocked = Model.attribute('isLocked');
|
||||
Discussion.prototype.canLock = Model.attribute('canLock');
|
||||
app.initializers.add('flarum-lock', () => {
|
||||
app.notificationComponents.discussionLocked = DiscussionLockedNotification;
|
||||
|
||||
addLockBadge();
|
||||
addLockControl();
|
||||
|
20
extensions/lock/js/tsconfig.json
Normal file
20
extensions/lock/js/tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
// Use Flarum's tsconfig as a starting point
|
||||
"extends": "flarum-tsconfig",
|
||||
// This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder
|
||||
// and also tells your Typescript server to read core's global typings for
|
||||
// access to `dayjs` and `$` in the global namespace.
|
||||
"include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"],
|
||||
"compilerOptions": {
|
||||
// This will output typings to `dist-typings`
|
||||
"declarationDir": "./dist-typings",
|
||||
"paths": {
|
||||
"flarum/*": ["../../../framework/core/js/dist-typings/*"],
|
||||
// TODO: remove after export registry system implemented
|
||||
// Without this, the old-style `@flarum/core` import is resolved to
|
||||
// source code in flarum/core instead of the dist typings.
|
||||
// This causes an inaccurate "duplicate export" error.
|
||||
"@flarum/core/*": ["../../../framework/core/js/dist-typings/*"],
|
||||
}
|
||||
}
|
||||
}
|
@@ -29,8 +29,8 @@ flarum-lock:
|
||||
|
||||
# These translations are displayed between posts in the post stream.
|
||||
post_stream:
|
||||
discussion_locked_text: "{username} locked the discussion."
|
||||
discussion_unlocked_text: "{username} unlocked the discussion."
|
||||
discussion_locked_text: "{username} locked the discussion {time}."
|
||||
discussion_unlocked_text: "{username} unlocked the discussion {time}."
|
||||
|
||||
# These translations are used in the Settings page.
|
||||
settings:
|
||||
|
@@ -18,7 +18,7 @@ class DiscussionPolicy extends AbstractPolicy
|
||||
/**
|
||||
* @param User $actor
|
||||
* @param Discussion $discussion
|
||||
* @return bool
|
||||
* @return string|void
|
||||
*/
|
||||
public function reply(User $actor, Discussion $discussion)
|
||||
{
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace Flarum\Lock\Post;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Flarum\Post\AbstractEventPost;
|
||||
use Flarum\Post\MergeableInterface;
|
||||
use Flarum\Post\Post;
|
||||
@@ -59,7 +60,7 @@ class DiscussionLockedPost extends AbstractEventPost implements MergeableInterfa
|
||||
$post = new static;
|
||||
|
||||
$post->content = static::buildContent($isLocked);
|
||||
$post->created_at = time();
|
||||
$post->created_at = Carbon::now();
|
||||
$post->discussion_id = $discussionId;
|
||||
$post->user_id = $userId;
|
||||
|
||||
|
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.5"
|
||||
"flarum/core": "^1.6"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
|
2
extensions/markdown/js/dist/admin.js
generated
vendored
2
extensions/markdown/js/dist/admin.js
generated
vendored
@@ -1,2 +1,2 @@
|
||||
(()=>{var t={n:o=>{var e=o&&o.__esModule?()=>o.default:()=>o;return t.d(e,{a:e}),e},d:(o,e)=>{for(var r in e)t.o(e,r)&&!t.o(o,r)&&Object.defineProperty(o,r,{enumerable:!0,get:e[r]})},o:(t,o)=>Object.prototype.hasOwnProperty.call(t,o),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},o={};(()=>{"use strict";t.r(o);const e=flarum.core.compat["admin/app"];var r=t.n(e);const i=flarum.core.compat["common/app"];var n=t.n(i);const a=flarum.core.compat["common/extend"],c=flarum.core.compat["common/components/TextEditor"];var l=t.n(c);const s=flarum.core.compat["common/utils/BasicEditorDriver"];var d=t.n(s);const u=flarum.core.compat["common/utils/styleSelectedText"];var f=t.n(u);function p(t,o){return p=Object.setPrototypeOf||function(t,o){return t.__proto__=o,t},p(t,o)}function h(t,o){t.prototype=Object.create(o.prototype),t.prototype.constructor=t,p(t,o)}const k=flarum.core.compat["common/Component"];var y=t.n(k),b=function(t){function o(){return t.apply(this,arguments)||this}return h(o,t),o.prototype.view=function(t){return m("div",{class:"MarkdownToolbar"},t.children)},o}(y());const x=flarum.core.compat["common/helpers/icon"];var v=t.n(x);const g=flarum.core.compat["common/components/Tooltip"];var _=t.n(g),w=function(t){function o(){return t.apply(this,arguments)||this}h(o,t);var e=o.prototype;return e.oncreate=function(o){t.prototype.oncreate.call(this,o)},e.view=function(){var t=m("button",{className:"Button Button--icon Button--link",type:"button","data-hotkey":this.attrs.hotkey,onkeydown:this.keydown.bind(this),onclick:this.attrs.onclick},v()(this.attrs.icon));return this.attrs.title?m(_(),{text:this.attrs.title},t):t},e.keydown=function(t){" "!==t.key&&"Enter"!==t.key||(t.preventDefault(),this.element.click())},o}(y());const T=flarum.core.compat["common/utils/ItemList"];var O=t.n(T),S=navigator.userAgent.match(/Macintosh/)?"⌘":"ctrl",I={header:{prefix:"### "},bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},strikethrough:{prefix:"~~",suffix:"~~",trimFirst:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](https://)",replaceNext:"https://",scanFor:"https?://"},image:{prefix:"",replaceNext:"https://",scanFor:"https?://"},unordered_list:{prefix:"- ",multiline:!0,surroundWithNewlines:!0},ordered_list:{prefix:"1. ",multiline:!0,orderedList:!0},spoiler:{prefix:">!",suffix:"!<",blockPrefix:">! ",multiline:!0,trimFirst:!0}},P=function(t,o){f()(o.el,I[t])};function j(t,o,e){return function(r){r.key===o&&(r.metaKey&&"⌘"===S||r.ctrlKey&&"ctrl"===S)&&(r.preventDefault(),P(t,e))}}function F(t){var o=this,e="function"==typeof t?t():new(O());function r(t,o){return n().translator.trans("flarum-markdown.lib.composer."+t+"_tooltip")+(o?" <"+S+"-"+o+">":"")}var i=function(t){return function(){return P(t,o.attrs.composer.editor)}};return e.add("header",m(w,{title:r("header"),icon:"fas fa-heading",onclick:i("header")}),1e3),e.add("bold",m(w,{title:r("bold","b"),icon:"fas fa-bold",onclick:i("bold")}),900),e.add("italic",m(w,{title:r("italic","i"),icon:"fas fa-italic",onclick:i("italic")}),800),e.add("strikethrough",m(w,{title:r("strikethrough"),icon:"fas fa-strikethrough",onclick:i("strikethrough")}),700),e.add("quote",m(w,{title:r("quote"),icon:"fas fa-quote-left",onclick:i("quote")}),600),e.add("spoiler",m(w,{title:r("spoiler"),icon:"fas fa-exclamation-triangle",onclick:i("spoiler")}),500),e.add("code",m(w,{title:r("code"),icon:"fas fa-code",onclick:i("code")}),400),e.add("link",m(w,{title:r("link"),icon:"fas fa-link",onclick:i("link")}),300),e.add("image",m(w,{title:r("image"),icon:"fas fa-image",onclick:i("image")}),200),e.add("unordered_list",m(w,{title:r("unordered_list"),icon:"fas fa-list-ul",onclick:i("unordered_list")}),100),e.add("ordered_list",m(w,{title:r("ordered_list"),icon:"fas fa-list-ol",onclick:i("ordered_list")}),0),e}r().initializers.add("flarum-markdown",(function(t){(0,a.extend)(d().prototype,"keyHandlers",(function(t){t.add("bold",j("bold","b",this)),t.add("italic",j("italic","i",this))})),l().prototype.markdownToolbarItems?(0,a.override)(l().prototype,"markdownToolbarItems",F):l().prototype.markdownToolbarItems=F,(0,a.extend)(l().prototype,"toolbarItems",(function(t){t.add("markdown",m(b,{for:this.textareaId,setShortcutHandler:function(t){return shortcutHandler=t}},this.markdownToolbarItems().toArray()),100)}))}))})(),module.exports=o})();
|
||||
(()=>{var t={n:o=>{var e=o&&o.__esModule?()=>o.default:()=>o;return t.d(e,{a:e}),e},d:(o,e)=>{for(var r in e)t.o(e,r)&&!t.o(o,r)&&Object.defineProperty(o,r,{enumerable:!0,get:e[r]})},o:(t,o)=>Object.prototype.hasOwnProperty.call(t,o),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},o={};(()=>{"use strict";t.r(o);const e=flarum.core.compat["admin/app"];var r=t.n(e);const i=flarum.core.compat["common/app"];var n=t.n(i);const a=flarum.core.compat["common/extend"],c=flarum.core.compat["common/components/TextEditor"];var l=t.n(c);const s=flarum.core.compat["common/utils/BasicEditorDriver"];var d=t.n(s);const u=flarum.core.compat["common/utils/styleSelectedText"];var f=t.n(u);function p(t,o){return p=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,o){return t.__proto__=o,t},p(t,o)}function h(t,o){t.prototype=Object.create(o.prototype),t.prototype.constructor=t,p(t,o)}const k=flarum.core.compat["common/Component"];var y=t.n(k),b=function(t){function o(){return t.apply(this,arguments)||this}return h(o,t),o.prototype.view=function(t){return m("div",{class:"MarkdownToolbar"},t.children)},o}(y());const x=flarum.core.compat["common/helpers/icon"];var v=t.n(x);const g=flarum.core.compat["common/components/Tooltip"];var _=t.n(g),w=function(t){function o(){return t.apply(this,arguments)||this}h(o,t);var e=o.prototype;return e.oncreate=function(o){t.prototype.oncreate.call(this,o)},e.view=function(){var t=m("button",{className:"Button Button--icon Button--link",type:"button","data-hotkey":this.attrs.hotkey,onkeydown:this.keydown.bind(this),onclick:this.attrs.onclick},v()(this.attrs.icon));return this.attrs.title?m(_(),{text:this.attrs.title},t):t},e.keydown=function(t){" "!==t.key&&"Enter"!==t.key||(t.preventDefault(),this.element.click())},o}(y());const O=flarum.core.compat["common/utils/ItemList"];var T=t.n(O),P=navigator.userAgent.match(/Macintosh/)?"⌘":"ctrl",S={header:{prefix:"### "},bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},strikethrough:{prefix:"~~",suffix:"~~",trimFirst:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](https://)",replaceNext:"https://",scanFor:"https?://"},image:{prefix:"",replaceNext:"https://",scanFor:"https?://"},unordered_list:{prefix:"- ",multiline:!0,surroundWithNewlines:!0},ordered_list:{prefix:"1. ",multiline:!0,orderedList:!0},spoiler:{prefix:">!",suffix:"!<",blockPrefix:">! ",multiline:!0,trimFirst:!0}},j=function(t,o){f()(o.el,S[t])};function I(t,o,e){return function(r){r.key===o&&(r.metaKey&&"⌘"===P||r.ctrlKey&&"ctrl"===P)&&(r.preventDefault(),j(t,e))}}function F(t){var o=this,e="function"==typeof t?t():new(T());function r(t,o){return n().translator.trans("flarum-markdown.lib.composer."+t+"_tooltip")+(o?" <"+P+"-"+o+">":"")}var i=function(t){return function(){return j(t,o.attrs.composer.editor)}};return e.add("header",m(w,{title:r("header"),icon:"fas fa-heading",onclick:i("header")}),1e3),e.add("bold",m(w,{title:r("bold","b"),icon:"fas fa-bold",onclick:i("bold")}),900),e.add("italic",m(w,{title:r("italic","i"),icon:"fas fa-italic",onclick:i("italic")}),800),e.add("strikethrough",m(w,{title:r("strikethrough"),icon:"fas fa-strikethrough",onclick:i("strikethrough")}),700),e.add("quote",m(w,{title:r("quote"),icon:"fas fa-quote-left",onclick:i("quote")}),600),e.add("spoiler",m(w,{title:r("spoiler"),icon:"fas fa-exclamation-triangle",onclick:i("spoiler")}),500),e.add("code",m(w,{title:r("code"),icon:"fas fa-code",onclick:i("code")}),400),e.add("link",m(w,{title:r("link"),icon:"fas fa-link",onclick:i("link")}),300),e.add("image",m(w,{title:r("image"),icon:"fas fa-image",onclick:i("image")}),200),e.add("unordered_list",m(w,{title:r("unordered_list"),icon:"fas fa-list-ul",onclick:i("unordered_list")}),100),e.add("ordered_list",m(w,{title:r("ordered_list"),icon:"fas fa-list-ol",onclick:i("ordered_list")}),0),e}r().initializers.add("flarum-markdown",(function(t){(0,a.extend)(d().prototype,"keyHandlers",(function(t){t.add("bold",I("bold","b",this)),t.add("italic",I("italic","i",this))})),l().prototype.markdownToolbarItems?(0,a.override)(l().prototype,"markdownToolbarItems",F):l().prototype.markdownToolbarItems=F,(0,a.extend)(l().prototype,"toolbarItems",(function(t){t.add("markdown",m(b,{for:this.textareaId,setShortcutHandler:function(t){return shortcutHandler=t}},this.markdownToolbarItems().toArray()),100)}))}))})(),module.exports=o})();
|
||||
//# sourceMappingURL=admin.js.map
|
2
extensions/markdown/js/dist/admin.js.map
generated
vendored
2
extensions/markdown/js/dist/admin.js.map
generated
vendored
File diff suppressed because one or more lines are too long
2
extensions/markdown/js/dist/forum.js
generated
vendored
2
extensions/markdown/js/dist/forum.js
generated
vendored
@@ -1,2 +1,2 @@
|
||||
(()=>{var t={n:o=>{var e=o&&o.__esModule?()=>o.default:()=>o;return t.d(e,{a:e}),e},d:(o,e)=>{for(var r in e)t.o(e,r)&&!t.o(o,r)&&Object.defineProperty(o,r,{enumerable:!0,get:e[r]})},o:(t,o)=>Object.prototype.hasOwnProperty.call(t,o),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},o={};(()=>{"use strict";t.r(o);const e=flarum.core.compat["forum/app"];var r=t.n(e);const i=flarum.core.compat["common/app"];var n=t.n(i);const a=flarum.core.compat["common/extend"],c=flarum.core.compat["common/components/TextEditor"];var l=t.n(c);const s=flarum.core.compat["common/utils/BasicEditorDriver"];var d=t.n(s);const u=flarum.core.compat["common/utils/styleSelectedText"];var f=t.n(u);function p(t,o){return p=Object.setPrototypeOf||function(t,o){return t.__proto__=o,t},p(t,o)}function h(t,o){t.prototype=Object.create(o.prototype),t.prototype.constructor=t,p(t,o)}const k=flarum.core.compat["common/Component"];var y=t.n(k),b=function(t){function o(){return t.apply(this,arguments)||this}return h(o,t),o.prototype.view=function(t){return m("div",{class:"MarkdownToolbar"},t.children)},o}(y());const x=flarum.core.compat["common/helpers/icon"];var v=t.n(x);const g=flarum.core.compat["common/components/Tooltip"];var _=t.n(g),w=function(t){function o(){return t.apply(this,arguments)||this}h(o,t);var e=o.prototype;return e.oncreate=function(o){t.prototype.oncreate.call(this,o)},e.view=function(){var t=m("button",{className:"Button Button--icon Button--link",type:"button","data-hotkey":this.attrs.hotkey,onkeydown:this.keydown.bind(this),onclick:this.attrs.onclick},v()(this.attrs.icon));return this.attrs.title?m(_(),{text:this.attrs.title},t):t},e.keydown=function(t){" "!==t.key&&"Enter"!==t.key||(t.preventDefault(),this.element.click())},o}(y());const T=flarum.core.compat["common/utils/ItemList"];var O=t.n(T),S=navigator.userAgent.match(/Macintosh/)?"⌘":"ctrl",I={header:{prefix:"### "},bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},strikethrough:{prefix:"~~",suffix:"~~",trimFirst:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](https://)",replaceNext:"https://",scanFor:"https?://"},image:{prefix:"",replaceNext:"https://",scanFor:"https?://"},unordered_list:{prefix:"- ",multiline:!0,surroundWithNewlines:!0},ordered_list:{prefix:"1. ",multiline:!0,orderedList:!0},spoiler:{prefix:">!",suffix:"!<",blockPrefix:">! ",multiline:!0,trimFirst:!0}},P=function(t,o){f()(o.el,I[t])};function j(t,o,e){return function(r){r.key===o&&(r.metaKey&&"⌘"===S||r.ctrlKey&&"ctrl"===S)&&(r.preventDefault(),P(t,e))}}function F(t){var o=this,e="function"==typeof t?t():new(O());function r(t,o){return n().translator.trans("flarum-markdown.lib.composer."+t+"_tooltip")+(o?" <"+S+"-"+o+">":"")}var i=function(t){return function(){return P(t,o.attrs.composer.editor)}};return e.add("header",m(w,{title:r("header"),icon:"fas fa-heading",onclick:i("header")}),1e3),e.add("bold",m(w,{title:r("bold","b"),icon:"fas fa-bold",onclick:i("bold")}),900),e.add("italic",m(w,{title:r("italic","i"),icon:"fas fa-italic",onclick:i("italic")}),800),e.add("strikethrough",m(w,{title:r("strikethrough"),icon:"fas fa-strikethrough",onclick:i("strikethrough")}),700),e.add("quote",m(w,{title:r("quote"),icon:"fas fa-quote-left",onclick:i("quote")}),600),e.add("spoiler",m(w,{title:r("spoiler"),icon:"fas fa-exclamation-triangle",onclick:i("spoiler")}),500),e.add("code",m(w,{title:r("code"),icon:"fas fa-code",onclick:i("code")}),400),e.add("link",m(w,{title:r("link"),icon:"fas fa-link",onclick:i("link")}),300),e.add("image",m(w,{title:r("image"),icon:"fas fa-image",onclick:i("image")}),200),e.add("unordered_list",m(w,{title:r("unordered_list"),icon:"fas fa-list-ul",onclick:i("unordered_list")}),100),e.add("ordered_list",m(w,{title:r("ordered_list"),icon:"fas fa-list-ol",onclick:i("ordered_list")}),0),e}r().initializers.add("flarum-markdown",(function(t){(0,a.extend)(d().prototype,"keyHandlers",(function(t){t.add("bold",j("bold","b",this)),t.add("italic",j("italic","i",this))})),l().prototype.markdownToolbarItems?(0,a.override)(l().prototype,"markdownToolbarItems",F):l().prototype.markdownToolbarItems=F,(0,a.extend)(l().prototype,"toolbarItems",(function(t){t.add("markdown",m(b,{for:this.textareaId,setShortcutHandler:function(t){return shortcutHandler=t}},this.markdownToolbarItems().toArray()),100)}))}))})(),module.exports=o})();
|
||||
(()=>{var t={n:o=>{var e=o&&o.__esModule?()=>o.default:()=>o;return t.d(e,{a:e}),e},d:(o,e)=>{for(var r in e)t.o(e,r)&&!t.o(o,r)&&Object.defineProperty(o,r,{enumerable:!0,get:e[r]})},o:(t,o)=>Object.prototype.hasOwnProperty.call(t,o),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},o={};(()=>{"use strict";t.r(o);const e=flarum.core.compat["forum/app"];var r=t.n(e);const i=flarum.core.compat["common/app"];var n=t.n(i);const a=flarum.core.compat["common/extend"],c=flarum.core.compat["common/components/TextEditor"];var l=t.n(c);const s=flarum.core.compat["common/utils/BasicEditorDriver"];var d=t.n(s);const u=flarum.core.compat["common/utils/styleSelectedText"];var f=t.n(u);function p(t,o){return p=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,o){return t.__proto__=o,t},p(t,o)}function h(t,o){t.prototype=Object.create(o.prototype),t.prototype.constructor=t,p(t,o)}const k=flarum.core.compat["common/Component"];var y=t.n(k),b=function(t){function o(){return t.apply(this,arguments)||this}return h(o,t),o.prototype.view=function(t){return m("div",{class:"MarkdownToolbar"},t.children)},o}(y());const x=flarum.core.compat["common/helpers/icon"];var v=t.n(x);const g=flarum.core.compat["common/components/Tooltip"];var _=t.n(g),w=function(t){function o(){return t.apply(this,arguments)||this}h(o,t);var e=o.prototype;return e.oncreate=function(o){t.prototype.oncreate.call(this,o)},e.view=function(){var t=m("button",{className:"Button Button--icon Button--link",type:"button","data-hotkey":this.attrs.hotkey,onkeydown:this.keydown.bind(this),onclick:this.attrs.onclick},v()(this.attrs.icon));return this.attrs.title?m(_(),{text:this.attrs.title},t):t},e.keydown=function(t){" "!==t.key&&"Enter"!==t.key||(t.preventDefault(),this.element.click())},o}(y());const O=flarum.core.compat["common/utils/ItemList"];var T=t.n(O),P=navigator.userAgent.match(/Macintosh/)?"⌘":"ctrl",S={header:{prefix:"### "},bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},strikethrough:{prefix:"~~",suffix:"~~",trimFirst:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](https://)",replaceNext:"https://",scanFor:"https?://"},image:{prefix:"",replaceNext:"https://",scanFor:"https?://"},unordered_list:{prefix:"- ",multiline:!0,surroundWithNewlines:!0},ordered_list:{prefix:"1. ",multiline:!0,orderedList:!0},spoiler:{prefix:">!",suffix:"!<",blockPrefix:">! ",multiline:!0,trimFirst:!0}},j=function(t,o){f()(o.el,S[t])};function I(t,o,e){return function(r){r.key===o&&(r.metaKey&&"⌘"===P||r.ctrlKey&&"ctrl"===P)&&(r.preventDefault(),j(t,e))}}function F(t){var o=this,e="function"==typeof t?t():new(T());function r(t,o){return n().translator.trans("flarum-markdown.lib.composer."+t+"_tooltip")+(o?" <"+P+"-"+o+">":"")}var i=function(t){return function(){return j(t,o.attrs.composer.editor)}};return e.add("header",m(w,{title:r("header"),icon:"fas fa-heading",onclick:i("header")}),1e3),e.add("bold",m(w,{title:r("bold","b"),icon:"fas fa-bold",onclick:i("bold")}),900),e.add("italic",m(w,{title:r("italic","i"),icon:"fas fa-italic",onclick:i("italic")}),800),e.add("strikethrough",m(w,{title:r("strikethrough"),icon:"fas fa-strikethrough",onclick:i("strikethrough")}),700),e.add("quote",m(w,{title:r("quote"),icon:"fas fa-quote-left",onclick:i("quote")}),600),e.add("spoiler",m(w,{title:r("spoiler"),icon:"fas fa-exclamation-triangle",onclick:i("spoiler")}),500),e.add("code",m(w,{title:r("code"),icon:"fas fa-code",onclick:i("code")}),400),e.add("link",m(w,{title:r("link"),icon:"fas fa-link",onclick:i("link")}),300),e.add("image",m(w,{title:r("image"),icon:"fas fa-image",onclick:i("image")}),200),e.add("unordered_list",m(w,{title:r("unordered_list"),icon:"fas fa-list-ul",onclick:i("unordered_list")}),100),e.add("ordered_list",m(w,{title:r("ordered_list"),icon:"fas fa-list-ol",onclick:i("ordered_list")}),0),e}r().initializers.add("flarum-markdown",(function(t){(0,a.extend)(d().prototype,"keyHandlers",(function(t){t.add("bold",I("bold","b",this)),t.add("italic",I("italic","i",this))})),l().prototype.markdownToolbarItems?(0,a.override)(l().prototype,"markdownToolbarItems",F):l().prototype.markdownToolbarItems=F,(0,a.extend)(l().prototype,"toolbarItems",(function(t){t.add("markdown",m(b,{for:this.textareaId,setShortcutHandler:function(t){return shortcutHandler=t}},this.markdownToolbarItems().toArray()),100)}))}))})(),module.exports=o})();
|
||||
//# sourceMappingURL=forum.js.map
|
2
extensions/markdown/js/dist/forum.js.map
generated
vendored
2
extensions/markdown/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.5"
|
||||
"flarum/core": "^1.6.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@@ -12,10 +12,12 @@ namespace Flarum\Mentions;
|
||||
use Flarum\Api\Controller;
|
||||
use Flarum\Api\Serializer\BasicPostSerializer;
|
||||
use Flarum\Api\Serializer\BasicUserSerializer;
|
||||
use Flarum\Api\Serializer\CurrentUserSerializer;
|
||||
use Flarum\Api\Serializer\GroupSerializer;
|
||||
use Flarum\Api\Serializer\PostSerializer;
|
||||
use Flarum\Approval\Event\PostWasApproved;
|
||||
use Flarum\Extend;
|
||||
use Flarum\Mentions\Notification\PostMentionedBlueprint;
|
||||
use Flarum\Mentions\Notification\UserMentionedBlueprint;
|
||||
use Flarum\Group\Group;
|
||||
use Flarum\Post\Event\Deleted;
|
||||
use Flarum\Post\Event\Hidden;
|
||||
use Flarum\Post\Event\Posted;
|
||||
@@ -37,13 +39,16 @@ return [
|
||||
->configure(ConfigureMentions::class)
|
||||
->render(Formatter\FormatPostMentions::class)
|
||||
->render(Formatter\FormatUserMentions::class)
|
||||
->render(Formatter\FormatGroupMentions::class)
|
||||
->unparse(Formatter\UnparsePostMentions::class)
|
||||
->unparse(Formatter\UnparseUserMentions::class),
|
||||
->unparse(Formatter\UnparseUserMentions::class)
|
||||
->parse(Formatter\CheckPermissions::class),
|
||||
|
||||
(new Extend\Model(Post::class))
|
||||
->belongsToMany('mentionedBy', Post::class, 'post_mentions_post', 'mentions_post_id', 'post_id')
|
||||
->belongsToMany('mentionsPosts', Post::class, 'post_mentions_post', 'post_id', 'mentions_post_id')
|
||||
->belongsToMany('mentionsUsers', User::class, 'post_mentions_user', 'post_id', 'mentions_user_id'),
|
||||
->belongsToMany('mentionsUsers', User::class, 'post_mentions_user', 'post_id', 'mentions_user_id')
|
||||
->belongsToMany('mentionsGroups', Group::class, 'post_mentions_group', 'post_id', 'mentions_group_id'),
|
||||
|
||||
new Extend\Locales(__DIR__.'/locale'),
|
||||
|
||||
@@ -51,25 +56,28 @@ return [
|
||||
->namespace('flarum-mentions', __DIR__.'/views'),
|
||||
|
||||
(new Extend\Notification())
|
||||
->type(PostMentionedBlueprint::class, PostSerializer::class, ['alert'])
|
||||
->type(UserMentionedBlueprint::class, PostSerializer::class, ['alert']),
|
||||
->type(Notification\PostMentionedBlueprint::class, PostSerializer::class, ['alert'])
|
||||
->type(Notification\UserMentionedBlueprint::class, PostSerializer::class, ['alert'])
|
||||
->type(Notification\GroupMentionedBlueprint::class, PostSerializer::class, ['alert']),
|
||||
|
||||
(new Extend\ApiSerializer(BasicPostSerializer::class))
|
||||
->hasMany('mentionedBy', BasicPostSerializer::class)
|
||||
->hasMany('mentionsPosts', BasicPostSerializer::class)
|
||||
->hasMany('mentionsUsers', BasicUserSerializer::class),
|
||||
->hasMany('mentionsUsers', BasicUserSerializer::class)
|
||||
->hasMany('mentionsGroups', GroupSerializer::class),
|
||||
|
||||
(new Extend\ApiController(Controller\ShowDiscussionController::class))
|
||||
->addInclude(['posts.mentionedBy', 'posts.mentionedBy.user', 'posts.mentionedBy.discussion'])
|
||||
->load([
|
||||
'posts.mentionsUsers', 'posts.mentionsPosts', 'posts.mentionsPosts.user', 'posts.mentionedBy',
|
||||
'posts.mentionedBy.mentionsPosts', 'posts.mentionedBy.mentionsPosts.user', 'posts.mentionedBy.mentionsUsers',
|
||||
'posts.mentionsGroups'
|
||||
]),
|
||||
|
||||
(new Extend\ApiController(Controller\ListDiscussionsController::class))
|
||||
->load([
|
||||
'firstPost.mentionsUsers', 'firstPost.mentionsPosts', 'firstPost.mentionsPosts.user',
|
||||
'lastPost.mentionsUsers', 'lastPost.mentionsPosts', 'lastPost.mentionsPosts.user'
|
||||
'firstPost.mentionsUsers', 'firstPost.mentionsPosts', 'firstPost.mentionsPosts.user', 'firstPost.mentionsGroups',
|
||||
'lastPost.mentionsUsers', 'lastPost.mentionsPosts', 'lastPost.mentionsPosts.user', 'lastPost.mentionsGroups'
|
||||
]),
|
||||
|
||||
(new Extend\ApiController(Controller\ShowPostController::class))
|
||||
@@ -80,13 +88,14 @@ return [
|
||||
->load([
|
||||
'mentionsUsers', 'mentionsPosts', 'mentionsPosts.user', 'mentionedBy',
|
||||
'mentionedBy.mentionsPosts', 'mentionedBy.mentionsPosts.user', 'mentionedBy.mentionsUsers',
|
||||
'mentionsGroups'
|
||||
]),
|
||||
|
||||
(new Extend\ApiController(Controller\CreatePostController::class))
|
||||
->addInclude(['mentionsPosts', 'mentionsPosts.mentionedBy']),
|
||||
->addOptionalInclude('mentionsGroups'),
|
||||
|
||||
(new Extend\ApiController(Controller\UpdatePostController::class))
|
||||
->addInclude(['mentionsPosts', 'mentionsPosts.mentionedBy']),
|
||||
->addOptionalInclude('mentionsGroups'),
|
||||
|
||||
(new Extend\ApiController(Controller\AbstractSerializeController::class))
|
||||
->prepareDataForSerialization(FilterVisiblePosts::class),
|
||||
@@ -98,9 +107,15 @@ return [
|
||||
->listen(Posted::class, Listener\UpdateMentionsMetadataWhenVisible::class)
|
||||
->listen(Restored::class, Listener\UpdateMentionsMetadataWhenVisible::class)
|
||||
->listen(Revised::class, Listener\UpdateMentionsMetadataWhenVisible::class)
|
||||
->listen(PostWasApproved::class, Listener\UpdateMentionsMetadataWhenVisible::class)
|
||||
->listen(Hidden::class, Listener\UpdateMentionsMetadataWhenInvisible::class)
|
||||
->listen(Deleted::class, Listener\UpdateMentionsMetadataWhenInvisible::class),
|
||||
|
||||
(new Extend\Filter(PostFilterer::class))
|
||||
->addFilter(Filter\MentionedFilter::class),
|
||||
|
||||
(new Extend\ApiSerializer(CurrentUserSerializer::class))
|
||||
->attribute('canMentionGroups', function (CurrentUserSerializer $serializer, User $user, array $attributes): bool {
|
||||
return $user->can('mentionGroups');
|
||||
})
|
||||
];
|
||||
|
2
extensions/mentions/js/dist/admin.js
generated
vendored
2
extensions/mentions/js/dist/admin.js
generated
vendored
@@ -1,2 +1,2 @@
|
||||
(()=>{var e={n:t=>{var a=t&&t.__esModule?()=>t.default:()=>t;return e.d(a,{a}),a},d:(t,a)=>{for(var r in a)e.o(a,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:a[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};(()=>{"use strict";e.r(t);const a=flarum.core.compat["admin/app"];var r=e.n(a);r().initializers.add("flarum-mentions",(function(){r().extensionData.for("flarum-mentions").registerSetting({setting:"flarum-mentions.allow_username_format",type:"boolean",label:r().translator.trans("flarum-mentions.admin.settings.allow_username_format_label"),help:r().translator.trans("flarum-mentions.admin.settings.allow_username_format_text")})}))})(),module.exports=t})();
|
||||
(()=>{var e={n:t=>{var r=t&&t.__esModule?()=>t.default:()=>t;return e.d(r,{a:r}),r},d:(t,r)=>{for(var a in r)e.o(r,a)&&!e.o(t,a)&&Object.defineProperty(t,a,{enumerable:!0,get:r[a]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};(()=>{"use strict";e.r(t);const r=flarum.core.compat["admin/app"];var a=e.n(r);a().initializers.add("flarum-mentions",(function(){a().extensionData.for("flarum-mentions").registerSetting({setting:"flarum-mentions.allow_username_format",type:"boolean",label:a().translator.trans("flarum-mentions.admin.settings.allow_username_format_label"),help:a().translator.trans("flarum-mentions.admin.settings.allow_username_format_text")}).registerPermission({permission:"mentionGroups",label:a().translator.trans("flarum-mentions.admin.permissions.mention_groups_label"),icon:"fas fa-at"},"start")}))})(),module.exports=t})();
|
||||
//# sourceMappingURL=admin.js.map
|
2
extensions/mentions/js/dist/admin.js.map
generated
vendored
2
extensions/mentions/js/dist/admin.js.map
generated
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,IACzBH,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,mBAAmB,WACtCA,IAAAA,cAAAA,IAAsB,mBAAmBC,gBAAgB,CACvDC,QAAS,wCACTC,KAAM,UACNC,MAAOJ,IAAAA,WAAAA,MAAqB,8DAC5BK,KAAML,IAAAA,WAAAA,MAAqB,8DAE9B,G","sources":["webpack://@flarum/mentions/webpack/bootstrap","webpack://@flarum/mentions/webpack/runtime/compat get default export","webpack://@flarum/mentions/webpack/runtime/define property getters","webpack://@flarum/mentions/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/mentions/webpack/runtime/make namespace object","webpack://@flarum/mentions/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/mentions/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-mentions', function () {\n app.extensionData.for('flarum-mentions').registerSetting({\n setting: 'flarum-mentions.allow_username_format',\n type: 'boolean',\n label: app.translator.trans('flarum-mentions.admin.settings.allow_username_format_label'),\n help: app.translator.trans('flarum-mentions.admin.settings.allow_username_format_text'),\n });\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerSetting","setting","type","label","help"],"sourceRoot":""}
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,mBAAmB,WACtCA,IAAAA,cAAAA,IACO,mBACJC,gBAAgB,CACfC,QAAS,wCACTC,KAAM,UACNC,MAAOJ,IAAAA,WAAAA,MAAqB,8DAC5BK,KAAML,IAAAA,WAAAA,MAAqB,+DAE5BM,mBACC,CACEC,WAAY,gBACZH,MAAOJ,IAAAA,WAAAA,MAAqB,0DAC5BQ,KAAM,aAER,QAEN,G","sources":["webpack://@flarum/mentions/webpack/bootstrap","webpack://@flarum/mentions/webpack/runtime/compat get default export","webpack://@flarum/mentions/webpack/runtime/define property getters","webpack://@flarum/mentions/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/mentions/webpack/runtime/make namespace object","webpack://@flarum/mentions/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/mentions/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-mentions', function () {\n app.extensionData\n .for('flarum-mentions')\n .registerSetting({\n setting: 'flarum-mentions.allow_username_format',\n type: 'boolean',\n label: app.translator.trans('flarum-mentions.admin.settings.allow_username_format_label'),\n help: app.translator.trans('flarum-mentions.admin.settings.allow_username_format_text'),\n })\n .registerPermission(\n {\n permission: 'mentionGroups',\n label: app.translator.trans('flarum-mentions.admin.permissions.mention_groups_label'),\n icon: 'fas fa-at',\n },\n 'start'\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerSetting","setting","type","label","help","registerPermission","permission","icon"],"sourceRoot":""}
|
2
extensions/mentions/js/dist/forum.js
generated
vendored
2
extensions/mentions/js/dist/forum.js
generated
vendored
File diff suppressed because one or more lines are too long
2
extensions/mentions/js/dist/forum.js.map
generated
vendored
2
extensions/mentions/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -1,10 +1,20 @@
|
||||
import app from 'flarum/admin/app';
|
||||
|
||||
app.initializers.add('flarum-mentions', function () {
|
||||
app.extensionData.for('flarum-mentions').registerSetting({
|
||||
setting: 'flarum-mentions.allow_username_format',
|
||||
type: 'boolean',
|
||||
label: app.translator.trans('flarum-mentions.admin.settings.allow_username_format_label'),
|
||||
help: app.translator.trans('flarum-mentions.admin.settings.allow_username_format_text'),
|
||||
});
|
||||
app.extensionData
|
||||
.for('flarum-mentions')
|
||||
.registerSetting({
|
||||
setting: 'flarum-mentions.allow_username_format',
|
||||
type: 'boolean',
|
||||
label: app.translator.trans('flarum-mentions.admin.settings.allow_username_format_label'),
|
||||
help: app.translator.trans('flarum-mentions.admin.settings.allow_username_format_text'),
|
||||
})
|
||||
.registerPermission(
|
||||
{
|
||||
permission: 'mentionGroups',
|
||||
label: app.translator.trans('flarum-mentions.admin.permissions.mention_groups_label'),
|
||||
icon: 'fas fa-at',
|
||||
},
|
||||
'start'
|
||||
);
|
||||
});
|
||||
|
@@ -7,9 +7,11 @@ import EditPostComposer from 'flarum/forum/components/EditPostComposer';
|
||||
import avatar from 'flarum/common/helpers/avatar';
|
||||
import usernameHelper from 'flarum/common/helpers/username';
|
||||
import highlight from 'flarum/common/helpers/highlight';
|
||||
import KeyboardNavigatable from 'flarum/forum/utils/KeyboardNavigatable';
|
||||
import KeyboardNavigatable from 'flarum/common/utils/KeyboardNavigatable';
|
||||
import { truncate } from 'flarum/common/utils/string';
|
||||
import { throttle } from 'flarum/common/utils/throttleDebounce';
|
||||
import Badge from 'flarum/common/components/Badge';
|
||||
import Group from 'flarum/common/models/Group';
|
||||
|
||||
import AutocompleteDropdown from './fragments/AutocompleteDropdown';
|
||||
import getMentionText from './utils/getMentionText';
|
||||
@@ -29,6 +31,7 @@ const throttledSearch = throttle(
|
||||
|
||||
buildSuggestions();
|
||||
});
|
||||
|
||||
searched.push(typedLower);
|
||||
}
|
||||
}
|
||||
@@ -66,6 +69,13 @@ export default function addComposerAutocomplete() {
|
||||
const returnedUsers = Array.from(app.store.all('users'));
|
||||
const returnedUserIds = new Set(returnedUsers.map((u) => u.id()));
|
||||
|
||||
// Store groups, but exclude the two virtual groups - 'Guest' and 'Member'.
|
||||
const returnedGroups = Array.from(
|
||||
app.store.all('groups').filter((group) => {
|
||||
return group.id() != Group.GUEST_ID && group.id() != Group.MEMBER_ID;
|
||||
})
|
||||
);
|
||||
|
||||
const applySuggestion = (replacement) => {
|
||||
this.attrs.composer.editor.replaceBeforeCursor(absMentionStart - 1, replacement + ' ');
|
||||
|
||||
@@ -124,12 +134,41 @@ export default function addComposerAutocomplete() {
|
||||
);
|
||||
};
|
||||
|
||||
const makeGroupSuggestion = function (group, replacement, content, className = '') {
|
||||
let groupName = group.namePlural().toLowerCase();
|
||||
|
||||
if (typed) {
|
||||
groupName = highlight(groupName, typed);
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
className={'PostPreview ' + className}
|
||||
onclick={() => applySuggestion(replacement)}
|
||||
onmouseenter={function () {
|
||||
dropdown.setIndex($(this).parent().index());
|
||||
}}
|
||||
>
|
||||
<span className="PostPreview-content">
|
||||
<Badge class={`Avatar Badge Badge--group--${group.id()} Badge-icon `} color={group.color()} type="group" icon={group.icon()} />
|
||||
<span className="username">{groupName}</span>
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
const userMatches = function (user) {
|
||||
const names = [user.username(), user.displayName()];
|
||||
|
||||
return names.some((name) => name.toLowerCase().substr(0, typed.length) === typed);
|
||||
};
|
||||
|
||||
const groupMatches = function (group) {
|
||||
const names = [group.nameSingular(), group.namePlural()];
|
||||
|
||||
return names.some((name) => name.toLowerCase().substr(0, typed.length) === typed);
|
||||
};
|
||||
|
||||
const buildSuggestions = () => {
|
||||
const suggestions = [];
|
||||
|
||||
@@ -141,6 +180,15 @@ export default function addComposerAutocomplete() {
|
||||
|
||||
suggestions.push(makeSuggestion(user, getMentionText(user), '', 'MentionsDropdown-user'));
|
||||
});
|
||||
|
||||
// ... or groups.
|
||||
if (app.session?.user?.canMentionGroups()) {
|
||||
returnedGroups.forEach((group) => {
|
||||
if (!groupMatches(group)) return;
|
||||
|
||||
suggestions.push(makeGroupSuggestion(group, getMentionText(undefined, undefined, group), '', 'MentionsDropdown-group'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// If the user is replying to a discussion, or if they are editing a
|
||||
|
@@ -1,7 +1,5 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import Model from 'flarum/common/Model';
|
||||
import Post from 'flarum/common/models/Post';
|
||||
import CommentPost from 'flarum/forum/components/CommentPost';
|
||||
import Link from 'flarum/common/components/Link';
|
||||
import PostPreview from 'flarum/forum/components/PostPreview';
|
||||
@@ -10,8 +8,6 @@ import username from 'flarum/common/helpers/username';
|
||||
import icon from 'flarum/common/helpers/icon';
|
||||
|
||||
export default function addMentionedByList() {
|
||||
Post.prototype.mentionedBy = Model.hasMany('mentionedBy');
|
||||
|
||||
function hidePreview() {
|
||||
this.$('.Post-mentionedBy-preview')
|
||||
.removeClass('in')
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import GroupMentionedNotification from './components/GroupMentionedNotification';
|
||||
import MentionsUserPage from './components/MentionsUserPage';
|
||||
import PostMentionedNotification from './components/PostMentionedNotification';
|
||||
import UserMentionedNotification from './components/UserMentionedNotification';
|
||||
@@ -13,6 +14,7 @@ export default {
|
||||
'mentions/components/MentionsUserPage': MentionsUserPage,
|
||||
'mentions/components/PostMentionedNotification': PostMentionedNotification,
|
||||
'mentions/components/UserMentionedNotification': UserMentionedNotification,
|
||||
'mentions/components/GroupMentionedNotification': GroupMentionedNotification,
|
||||
'mentions/fragments/AutocompleteDropdown': AutocompleteDropdown,
|
||||
'mentions/fragments/PostQuoteButton': PostQuoteButton,
|
||||
'mentions/utils/getCleanDisplayName': getCleanDisplayName,
|
||||
|
@@ -0,0 +1,25 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import Notification from 'flarum/forum/components/Notification';
|
||||
import { truncate } from 'flarum/common/utils/string';
|
||||
|
||||
export default class GroupMentionedNotification extends Notification {
|
||||
icon() {
|
||||
return 'fas fa-at';
|
||||
}
|
||||
|
||||
href() {
|
||||
const post = this.attrs.notification.subject();
|
||||
|
||||
return app.route.discussion(post.discussion(), post.number());
|
||||
}
|
||||
|
||||
content() {
|
||||
const user = this.attrs.notification.fromUser();
|
||||
|
||||
return app.translator.trans('flarum-mentions.forum.notifications.group_mentioned_text', { user });
|
||||
}
|
||||
|
||||
excerpt() {
|
||||
return truncate(this.attrs.notification.subject().contentPlain(), 200);
|
||||
}
|
||||
}
|
15
extensions/mentions/js/src/forum/extend.ts
Normal file
15
extensions/mentions/js/src/forum/extend.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import Extend from 'flarum/common/extenders';
|
||||
import Post from 'flarum/common/models/Post';
|
||||
import User from 'flarum/common/models/User';
|
||||
import MentionsUserPage from './components/MentionsUserPage';
|
||||
|
||||
export default [
|
||||
new Extend.Routes() //
|
||||
.add('user.mentions', '/u/:username/mentions', MentionsUserPage),
|
||||
|
||||
new Extend.Model(Post) //
|
||||
.hasMany<Post>('mentionedBy'),
|
||||
|
||||
new Extend.Model(User) //
|
||||
.attribute<boolean>('canMentionGroups'),
|
||||
];
|
@@ -2,6 +2,8 @@ import { extend } from 'flarum/common/extend';
|
||||
import app from 'flarum/forum/app';
|
||||
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
||||
import { getPlainContent } from 'flarum/common/utils/string';
|
||||
import textContrastClass from 'flarum/common/helpers/textContrastClass';
|
||||
import Post from 'flarum/forum/components/Post';
|
||||
|
||||
import addPostMentionPreviews from './addPostMentionPreviews';
|
||||
import addMentionedByList from './addMentionedByList';
|
||||
@@ -10,9 +12,13 @@ import addPostQuoteButton from './addPostQuoteButton';
|
||||
import addComposerAutocomplete from './addComposerAutocomplete';
|
||||
import PostMentionedNotification from './components/PostMentionedNotification';
|
||||
import UserMentionedNotification from './components/UserMentionedNotification';
|
||||
import GroupMentionedNotification from './components/GroupMentionedNotification';
|
||||
import UserPage from 'flarum/forum/components/UserPage';
|
||||
import LinkButton from 'flarum/common/components/LinkButton';
|
||||
import MentionsUserPage from './components/MentionsUserPage';
|
||||
import User from 'flarum/common/models/User';
|
||||
import Model from 'flarum/common/Model';
|
||||
|
||||
export { default as extend } from './extend';
|
||||
|
||||
app.initializers.add('flarum-mentions', function () {
|
||||
// For every mention of a post inside a post's content, set up a hover handler
|
||||
@@ -36,6 +42,7 @@ app.initializers.add('flarum-mentions', function () {
|
||||
|
||||
app.notificationComponents.postMentioned = PostMentionedNotification;
|
||||
app.notificationComponents.userMentioned = UserMentionedNotification;
|
||||
app.notificationComponents.groupMentioned = GroupMentionedNotification;
|
||||
|
||||
// Add notification preferences.
|
||||
extend(NotificationGrid.prototype, 'notificationTypes', function (items) {
|
||||
@@ -50,10 +57,15 @@ app.initializers.add('flarum-mentions', function () {
|
||||
icon: 'fas fa-at',
|
||||
label: app.translator.trans('flarum-mentions.forum.settings.notify_user_mentioned_label'),
|
||||
});
|
||||
|
||||
items.add('groupMentioned', {
|
||||
name: 'groupMentioned',
|
||||
icon: 'fas fa-at',
|
||||
label: app.translator.trans('flarum-mentions.forum.settings.notify_group_mentioned_label'),
|
||||
});
|
||||
});
|
||||
|
||||
// Add mentions tab in user profile
|
||||
app.routes['user.mentions'] = { path: '/u/:username/mentions', component: MentionsUserPage };
|
||||
extend(UserPage.prototype, 'navItems', function (items) {
|
||||
const user = this.user;
|
||||
items.add(
|
||||
@@ -72,6 +84,13 @@ app.initializers.add('flarum-mentions', function () {
|
||||
|
||||
// Remove post mentions when rendering post previews.
|
||||
getPlainContent.removeSelectors.push('a.PostMention');
|
||||
|
||||
// Apply color contrast fix on group mentions.
|
||||
extend(Post.prototype, 'oncreate', function () {
|
||||
this.$('.GroupMention--colored').each(function () {
|
||||
this.classList.add(textContrastClass(getComputedStyle(this).getPropertyValue('--group-color')));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
export * from './utils/textFormatter';
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import getCleanDisplayName, { shouldUseOldFormat } from './getCleanDisplayName';
|
||||
|
||||
/**
|
||||
* Fetches the mention text for a specified user (and optionally a post ID for replies).
|
||||
* Fetches the mention text for a specified user (and optionally a post ID for replies, or group).
|
||||
*
|
||||
* Automatically determines which mention syntax to be used based on the option in the
|
||||
* admin dashboard. Also performs display name clean-up automatically.
|
||||
@@ -17,9 +17,13 @@ import getCleanDisplayName, { shouldUseOldFormat } from './getCleanDisplayName';
|
||||
* @example <caption>Using old syntax</caption>
|
||||
* // '@username'
|
||||
* getMentionText(User) // User's username is 'username'
|
||||
*
|
||||
* @example <caption>Group mention</caption>
|
||||
* // '@"Mods"#g4'
|
||||
* getMentionText(undefined, undefined, group) // Group display name is 'Mods', group ID is 4
|
||||
*/
|
||||
export default function getMentionText(user, postId) {
|
||||
if (postId === undefined) {
|
||||
export default function getMentionText(user, postId, group) {
|
||||
if (user !== undefined && postId === undefined) {
|
||||
if (shouldUseOldFormat()) {
|
||||
// Plain @username
|
||||
const cleanText = getCleanDisplayName(user, false);
|
||||
@@ -28,9 +32,14 @@ export default function getMentionText(user, postId) {
|
||||
// @"Display name"#UserID
|
||||
const cleanText = getCleanDisplayName(user);
|
||||
return `@"${cleanText}"#${user.id()}`;
|
||||
} else {
|
||||
} else if (user !== undefined && postId !== undefined) {
|
||||
// @"Display name"#pPostID
|
||||
const cleanText = getCleanDisplayName(user);
|
||||
return `@"${cleanText}"#p${postId}`;
|
||||
} else if (group !== undefined) {
|
||||
// @"Name Plural"#gGroupID
|
||||
return `@"${group.namePlural()}"#g${group.id()}`;
|
||||
} else {
|
||||
throw 'No parameters were passed';
|
||||
}
|
||||
}
|
||||
|
@@ -31,3 +31,19 @@ export function filterPostMentions(tag) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export function filterGroupMentions(tag) {
|
||||
if (app.session?.user?.canMentionGroups()) {
|
||||
const group = app.store.getById('groups', tag.getAttribute('id'));
|
||||
|
||||
if (group) {
|
||||
tag.setAttribute('groupname', extractText(group.namePlural()));
|
||||
tag.setAttribute('icon', group.icon());
|
||||
tag.setAttribute('color', group.color());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
tag.invalidate();
|
||||
}
|
||||
|
20
extensions/mentions/js/tsconfig.json
Normal file
20
extensions/mentions/js/tsconfig.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
// Use Flarum's tsconfig as a starting point
|
||||
"extends": "flarum-tsconfig",
|
||||
// This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder
|
||||
// and also tells your Typescript server to read core's global typings for
|
||||
// access to `dayjs` and `$` in the global namespace.
|
||||
"include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"],
|
||||
"compilerOptions": {
|
||||
// This will output typings to `dist-typings`
|
||||
"declarationDir": "./dist-typings",
|
||||
"paths": {
|
||||
"flarum/*": ["../../../framework/core/js/dist-typings/*"],
|
||||
// TODO: remove after export registry system implemented
|
||||
// Without this, the old-style `@flarum/core` import is resolved to
|
||||
// source code in flarum/core instead of the dist typings.
|
||||
// This causes an inaccurate "duplicate export" error.
|
||||
"@flarum/core/*": ["../../../framework/core/js/dist-typings/*"],
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,20 +1,20 @@
|
||||
.PostMention, .UserMention {
|
||||
background: @control-bg;
|
||||
color: @control-color;
|
||||
.PostMention, .UserMention, .GroupMention {
|
||||
background: var(--control-bg);
|
||||
color: var(--control-color);
|
||||
border-radius: @border-radius;
|
||||
padding: 2px 5px;
|
||||
border: 0 !important;
|
||||
font-weight: 600;
|
||||
|
||||
blockquote & {
|
||||
background: @body-bg;
|
||||
background: var(--body-bg);
|
||||
}
|
||||
&:hover,
|
||||
&:active {
|
||||
color: @link-color;
|
||||
color: var(--link-color);
|
||||
}
|
||||
}
|
||||
.UserMention, .PostMention {
|
||||
.UserMention, .PostMention, .GroupMention {
|
||||
&--deleted {
|
||||
opacity: 0.8;
|
||||
filter: grayscale(1);
|
||||
@@ -97,6 +97,23 @@
|
||||
position: absolute;
|
||||
.Button--color(@tooltip-color, @tooltip-bg);
|
||||
}
|
||||
.GroupMention {
|
||||
background-color: var(--group-color, var(--control-bg));
|
||||
color: var(--control-color);
|
||||
--link-color: currentColor;
|
||||
|
||||
&--colored {
|
||||
--control-color: var(--contrast-color, var(--body-bg));
|
||||
--link-color: var(--control-color);
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
.MentionsDropdown .Badge {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
@media @phone {
|
||||
.MentionsDropdown {
|
||||
|
@@ -7,6 +7,9 @@ flarum-mentions:
|
||||
# Translations in this namespace are used by the admin interface.
|
||||
admin:
|
||||
|
||||
# These translations are used in the mentions permissions
|
||||
permissions:
|
||||
mention_groups_label: Mention groups
|
||||
# These translations are used in the mentions Settings page.
|
||||
settings:
|
||||
allow_username_format_label: Allow username mention format (@Username)
|
||||
@@ -19,7 +22,7 @@ flarum-mentions:
|
||||
|
||||
# These translations are used by the composer (reply autocompletion function).
|
||||
composer:
|
||||
mention_tooltip: Mention a user or post
|
||||
mention_tooltip: Mention a user, group or post
|
||||
reply_to_post_text: "Reply to #{number}"
|
||||
|
||||
# These translations are used by the Notifications dropdown, a.k.a. "the bell".
|
||||
@@ -27,6 +30,7 @@ flarum-mentions:
|
||||
others_text: => core.ref.some_others
|
||||
post_mentioned_text: "{username} replied to your post" # Can be pluralized to agree with the number of users!
|
||||
user_mentioned_text: "{username} mentioned you"
|
||||
group_mentioned_text: "{username} mentioned a group you're a member of"
|
||||
|
||||
# These translations are displayed beneath individual posts.
|
||||
post:
|
||||
@@ -41,6 +45,7 @@ flarum-mentions:
|
||||
settings:
|
||||
notify_post_mentioned_label: Someone replies to one of my posts
|
||||
notify_user_mentioned_label: Someone mentions me in a post
|
||||
notify_group_mentioned_label: Someone mentions a group I'm a member of in a post
|
||||
|
||||
# These translations are used in the user profile page and profile popup.
|
||||
user:
|
||||
@@ -50,6 +55,9 @@ flarum-mentions:
|
||||
post_mention:
|
||||
deleted_text: "[unknown]"
|
||||
|
||||
group_mention:
|
||||
deleted_text: "[unknown group]"
|
||||
|
||||
# Translations in this namespace are used in emails sent by the forum.
|
||||
email:
|
||||
|
||||
@@ -80,4 +88,16 @@ flarum-mentions:
|
||||
---
|
||||
|
||||
{content}
|
||||
# These translations are used in emails sent when a group is mentioned
|
||||
group_mentioned:
|
||||
subject: "{mentioner_display_name} mentioned a group you're a member of in {title}"
|
||||
body: |
|
||||
Hey {recipient_display_name}!
|
||||
|
||||
{mentioner_display_name} mentioned a group you're a member of in {title}.
|
||||
|
||||
{url}
|
||||
|
||||
---
|
||||
|
||||
{content}
|
||||
|
@@ -19,7 +19,7 @@ return [
|
||||
// do this manually because dbal doesn't recognize timestamp columns
|
||||
$connection = $schema->getConnection();
|
||||
$prefix = $connection->getTablePrefix();
|
||||
$connection->statement("ALTER TABLE `${prefix}post_mentions_post` MODIFY created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP");
|
||||
$connection->statement("ALTER TABLE `{$prefix}post_mentions_post` MODIFY created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP");
|
||||
},
|
||||
|
||||
'down' => function (Builder $schema) {
|
||||
|
@@ -19,7 +19,7 @@ return [
|
||||
// do this manually because dbal doesn't recognize timestamp columns
|
||||
$connection = $schema->getConnection();
|
||||
$prefix = $connection->getTablePrefix();
|
||||
$connection->statement("ALTER TABLE `${prefix}post_mentions_user` MODIFY created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP");
|
||||
$connection->statement("ALTER TABLE `{$prefix}post_mentions_user` MODIFY created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP");
|
||||
},
|
||||
|
||||
'down' => function (Builder $schema) {
|
||||
|
@@ -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.
|
||||
*/
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Schema\Builder;
|
||||
|
||||
return [
|
||||
'up' => function (Builder $schema) {
|
||||
$schema->create('post_mentions_group', function (Blueprint $table) {
|
||||
$table->integer('post_id')->unsigned();
|
||||
$table->integer('mentions_group_id')->unsigned();
|
||||
$table->dateTime('created_at')->useCurrent()->nullable();
|
||||
$table->primary(['post_id', 'mentions_group_id']);
|
||||
|
||||
$table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');
|
||||
$table->foreign('mentions_group_id')->references('id')->on('groups')->onDelete('cascade');
|
||||
});
|
||||
},
|
||||
|
||||
'down' => function (Builder $schema) {
|
||||
$schema->drop('post_mentions_group');
|
||||
}
|
||||
];
|
@@ -9,11 +9,13 @@
|
||||
|
||||
namespace Flarum\Mentions;
|
||||
|
||||
use Flarum\Group\Group;
|
||||
use Flarum\Http\UrlGenerator;
|
||||
use Flarum\Post\CommentPost;
|
||||
use Flarum\Post\PostRepository;
|
||||
use Flarum\Settings\SettingsRepositoryInterface;
|
||||
use Flarum\User\User;
|
||||
use s9e\TextFormatter\Configurator;
|
||||
use s9e\TextFormatter\Parser\Tag;
|
||||
|
||||
class ConfigureMentions
|
||||
{
|
||||
@@ -34,9 +36,10 @@ class ConfigureMentions
|
||||
{
|
||||
$this->configureUserMentions($config);
|
||||
$this->configurePostMentions($config);
|
||||
$this->configureGroupMentions($config);
|
||||
}
|
||||
|
||||
private function configureUserMentions(Configurator $config)
|
||||
private function configureUserMentions(Configurator $config): void
|
||||
{
|
||||
$config->rendering->parameters['PROFILE_URL'] = $this->url->to('forum')->route('user', ['username' => '']);
|
||||
|
||||
@@ -63,9 +66,8 @@ class ConfigureMentions
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tag
|
||||
*
|
||||
* @return bool
|
||||
* @param Tag $tag
|
||||
* @return bool|void
|
||||
*/
|
||||
public static function addUserId($tag)
|
||||
{
|
||||
@@ -78,7 +80,7 @@ class ConfigureMentions
|
||||
}
|
||||
|
||||
if (isset($user)) {
|
||||
$tag->setAttribute('id', $user->id);
|
||||
$tag->setAttribute('id', (string) $user->id);
|
||||
$tag->setAttribute('displayname', $user->display_name);
|
||||
|
||||
return true;
|
||||
@@ -87,7 +89,7 @@ class ConfigureMentions
|
||||
$tag->invalidate();
|
||||
}
|
||||
|
||||
private function configurePostMentions(Configurator $config)
|
||||
private function configurePostMentions(Configurator $config): void
|
||||
{
|
||||
$config->rendering->parameters['DISCUSSION_URL'] = $this->url->to('forum')->route('discussion', ['id' => '']);
|
||||
|
||||
@@ -112,22 +114,25 @@ class ConfigureMentions
|
||||
|
||||
$tag->filterChain
|
||||
->prepend([static::class, 'addPostId'])
|
||||
->setJS('function(tag) { return flarum.extensions["flarum-mentions"].filterPostMentions(tag); }');
|
||||
->setJS('function(tag) { return flarum.extensions["flarum-mentions"].filterPostMentions(tag); }')
|
||||
->addParameterByName('actor');
|
||||
|
||||
$config->Preg->match('/\B@["|“](?<displayname>((?!"#[a-z]{0,3}[0-9]+).)+)["|”]#p(?<id>[0-9]+)\b/', $tagName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tag
|
||||
* @return bool
|
||||
* @param Tag $tag
|
||||
* @return bool|void
|
||||
*/
|
||||
public static function addPostId($tag)
|
||||
public static function addPostId($tag, User $actor)
|
||||
{
|
||||
$post = CommentPost::find($tag->getAttribute('id'));
|
||||
$post = resolve(PostRepository::class)
|
||||
->queryVisibleTo($actor)
|
||||
->find($tag->getAttribute('id'));
|
||||
|
||||
if ($post) {
|
||||
$tag->setAttribute('discussionid', (int) $post->discussion_id);
|
||||
$tag->setAttribute('number', (int) $post->number);
|
||||
$tag->setAttribute('discussionid', (string) $post->discussion_id);
|
||||
$tag->setAttribute('number', (string) $post->number);
|
||||
|
||||
if ($post->user) {
|
||||
$tag->setAttribute('displayname', $post->user->display_name);
|
||||
@@ -136,4 +141,71 @@ class ConfigureMentions
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private function configureGroupMentions(Configurator $config)
|
||||
{
|
||||
$tagName = 'GROUPMENTION';
|
||||
|
||||
$tag = $config->tags->add($tagName);
|
||||
$tag->attributes->add('groupname');
|
||||
$tag->attributes->add('icon');
|
||||
$tag->attributes->add('color');
|
||||
$tag->attributes->add('id')->filterChain->append('#uint');
|
||||
|
||||
$tag->template = '
|
||||
<xsl:choose>
|
||||
<xsl:when test="@deleted != 1">
|
||||
<xsl:choose>
|
||||
<xsl:when test="string(@color) != \'\'">
|
||||
<span class="GroupMention GroupMention--colored" style="--group-color:{@color};">
|
||||
<span class="GroupMention-name">@<xsl:value-of select="@groupname"/></span>
|
||||
<xsl:if test="string(@icon) != \'\'">
|
||||
<i class="icon {@icon}"></i>
|
||||
</xsl:if>
|
||||
</span>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<span class="GroupMention">
|
||||
<span class="GroupMention-name">@<xsl:value-of select="@groupname"/></span>
|
||||
<xsl:if test="string(@icon) != \'\'">
|
||||
<i class="icon {@icon}"></i>
|
||||
</xsl:if>
|
||||
</span>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<span class="GroupMention GroupMention--deleted">
|
||||
<span class="GroupMention-name">@<xsl:value-of select="@groupname"/></span>
|
||||
<xsl:if test="string(@icon) != \'\'">
|
||||
<i class="icon {@icon}"></i>
|
||||
</xsl:if>
|
||||
</span>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>';
|
||||
$tag->filterChain->prepend([static::class, 'addGroupId'])
|
||||
->setJS('function(tag) { return flarum.extensions["flarum-mentions"].filterGroupMentions(tag); }');
|
||||
|
||||
$config->Preg->match('/\B@["|“](?<groupname>((?!"#[a-z]{0,3}[0-9]+).)+)["|”]#g(?<id>[0-9]+)\b/', $tagName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tag
|
||||
* @return bool|void
|
||||
*/
|
||||
public static function addGroupId($tag)
|
||||
{
|
||||
$group = Group::find($tag->getAttribute('id'));
|
||||
|
||||
if (isset($group) && ! in_array($group->id, [Group::GUEST_ID, Group::MEMBER_ID])) {
|
||||
$tag->setAttribute('id', $group->id);
|
||||
$tag->setAttribute('groupname', $group->name_plural);
|
||||
$tag->setAttribute('icon', $group->icon ?? 'fas fa-at');
|
||||
$tag->setAttribute('color', $group->color);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$tag->invalidate();
|
||||
}
|
||||
}
|
||||
|
@@ -54,8 +54,8 @@ class FilterVisiblePosts
|
||||
|| $controller instanceof Controller\CreatePostController
|
||||
|| $controller instanceof Controller\UpdatePostController) {
|
||||
$relations = [
|
||||
'mentionsUsers', 'mentionsPosts', 'mentionsPosts.user', 'mentionedBy',
|
||||
'mentionedBy.mentionsPosts', 'mentionedBy.mentionsPosts.user', 'mentionedBy.mentionsUsers'
|
||||
'mentionsUsers', 'mentionsPosts', 'mentionsPosts.user', 'mentionedBy', 'mentionsGroups',
|
||||
'mentionedBy.mentionsPosts', 'mentionedBy.mentionsPosts.user', 'mentionedBy.mentionsUsers', 'mentionedBy.mentionsGroups.group'
|
||||
];
|
||||
|
||||
$posts = [$data];
|
||||
|
26
extensions/mentions/src/Formatter/CheckPermissions.php
Normal file
26
extensions/mentions/src/Formatter/CheckPermissions.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?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\Mentions\Formatter;
|
||||
|
||||
use Flarum\User\User;
|
||||
use s9e\TextFormatter\Parser;
|
||||
|
||||
class CheckPermissions
|
||||
{
|
||||
public function __invoke(Parser $parser, $content, string $text, ?User $actor): string
|
||||
{
|
||||
// Check user has `mentionGroups` permission, if not, remove the `GROUPMENTION` tag from the parser.
|
||||
if ($actor && $actor->cannot('mentionGroups')) {
|
||||
$parser->disableTag('GROUPMENTION');
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
}
|
59
extensions/mentions/src/Formatter/FormatGroupMentions.php
Normal file
59
extensions/mentions/src/Formatter/FormatGroupMentions.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?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\Mentions\Formatter;
|
||||
|
||||
use Flarum\Group\Group;
|
||||
use Flarum\Post\Post;
|
||||
use s9e\TextFormatter\Renderer;
|
||||
use s9e\TextFormatter\Utils;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class FormatGroupMentions
|
||||
{
|
||||
/**
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
private $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure rendering for group mentions.
|
||||
*
|
||||
* @param \s9e\TextFormatter\Renderer $renderer
|
||||
* @param mixed $context
|
||||
* @param string $xml
|
||||
* @return string
|
||||
*/
|
||||
public function __invoke(Renderer $renderer, $context, string $xml): string
|
||||
{
|
||||
return Utils::replaceAttributes($xml, 'GROUPMENTION', function ($attributes) use ($context) {
|
||||
$group = (($context && isset($context->getRelations()['mentionsGroups'])) || $context instanceof Post)
|
||||
? $context->mentionsGroups->find($attributes['id'])
|
||||
: Group::find($attributes['id']);
|
||||
|
||||
if ($group) {
|
||||
$attributes['groupname'] = $group->name_plural;
|
||||
$attributes['icon'] = $group->icon ?? 'fas fa-at';
|
||||
$attributes['color'] = $group->color;
|
||||
$attributes['deleted'] = false;
|
||||
} else {
|
||||
$attributes['groupname'] = $this->translator->trans('flarum-mentions.forum.group_mention.deleted_text');
|
||||
$attributes['icon'] = '';
|
||||
$attributes['deleted'] = true;
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
});
|
||||
}
|
||||
}
|
@@ -29,11 +29,11 @@ class FormatPostMentions
|
||||
/**
|
||||
* Configure rendering for post mentions.
|
||||
*
|
||||
* @param s9e\TextFormatter\Renderer $renderer
|
||||
* @param \s9e\TextFormatter\Renderer $renderer
|
||||
* @param mixed $context
|
||||
* @param string|null $xml
|
||||
* @param Psr\Http\Message\ServerRequestInterface $request
|
||||
* @return void
|
||||
* @param \Psr\Http\Message\ServerRequestInterface $request
|
||||
* @return string
|
||||
*/
|
||||
public function __invoke(Renderer $renderer, $context, $xml, Request $request = null)
|
||||
{
|
||||
|
@@ -37,9 +37,9 @@ class FormatUserMentions
|
||||
/**
|
||||
* Configure rendering for user mentions.
|
||||
*
|
||||
* @param s9e\TextFormatter\Renderer $renderer
|
||||
* @param \s9e\TextFormatter\Renderer $renderer
|
||||
* @param mixed $context
|
||||
* @param string|null $xml
|
||||
* @param string $xml
|
||||
* @return string $xml to be rendered
|
||||
*/
|
||||
public function __invoke(Renderer $renderer, $context, string $xml)
|
||||
|
@@ -40,5 +40,8 @@ class UpdateMentionsMetadataWhenInvisible
|
||||
|
||||
// Remove post mentions
|
||||
$event->post->mentionsPosts()->sync([]);
|
||||
|
||||
// Remove group mentions
|
||||
$event->post->mentionsGroups()->sync([]);
|
||||
}
|
||||
}
|
||||
|
@@ -9,9 +9,12 @@
|
||||
|
||||
namespace Flarum\Mentions\Listener;
|
||||
|
||||
use Flarum\Approval\Event\PostWasApproved;
|
||||
use Flarum\Mentions\Notification\GroupMentionedBlueprint;
|
||||
use Flarum\Mentions\Notification\PostMentionedBlueprint;
|
||||
use Flarum\Mentions\Notification\UserMentionedBlueprint;
|
||||
use Flarum\Notification\NotificationSyncer;
|
||||
use Flarum\Post\CommentPost;
|
||||
use Flarum\Post\Event\Posted;
|
||||
use Flarum\Post\Event\Restored;
|
||||
use Flarum\Post\Event\Revised;
|
||||
@@ -35,11 +38,15 @@ class UpdateMentionsMetadataWhenVisible
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Posted|Restored|Revised $event
|
||||
* @param Posted|Restored|Revised|PostWasApproved $event
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
$content = $event->post->parsedContent;
|
||||
if (! $event->post instanceof CommentPost) {
|
||||
return;
|
||||
}
|
||||
|
||||
$content = $event->post->parsed_content;
|
||||
|
||||
$this->syncUserMentions(
|
||||
$event->post,
|
||||
@@ -50,6 +57,11 @@ class UpdateMentionsMetadataWhenVisible
|
||||
$event->post,
|
||||
Utils::getAttributeValues($content, 'POSTMENTION', 'id')
|
||||
);
|
||||
|
||||
$this->syncGroupMentions(
|
||||
$event->post,
|
||||
Utils::getAttributeValues($content, 'GROUPMENTION', 'id')
|
||||
);
|
||||
}
|
||||
|
||||
protected function syncUserMentions(Post $post, array $mentioned)
|
||||
@@ -84,4 +96,21 @@ class UpdateMentionsMetadataWhenVisible
|
||||
$this->notifications->sync(new PostMentionedBlueprint($post, $reply), [$post->user]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function syncGroupMentions(Post $post, array $mentioned)
|
||||
{
|
||||
$post->mentionsGroups()->sync($mentioned);
|
||||
$post->unsetRelation('mentionsGroups');
|
||||
|
||||
$users = User::whereHas('groups', function ($query) use ($mentioned) {
|
||||
$query->whereIn('id', $mentioned);
|
||||
})
|
||||
->get()
|
||||
->filter(function (User $user) use ($post) {
|
||||
return $post->isVisibleTo($user) && $user->id !== $post->user_id;
|
||||
})
|
||||
->all();
|
||||
|
||||
$this->notifications->sync(new GroupMentionedBlueprint($post), $users);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,89 @@
|
||||
<?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\Mentions\Notification;
|
||||
|
||||
use Flarum\Notification\Blueprint\BlueprintInterface;
|
||||
use Flarum\Notification\MailableInterface;
|
||||
use Flarum\Post\Post;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class GroupMentionedBlueprint 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFromUser()
|
||||
{
|
||||
return $this->post->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getEmailView()
|
||||
{
|
||||
return ['text' => 'flarum-mentions::emails.groupMentioned'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getEmailSubject(TranslatorInterface $translator)
|
||||
{
|
||||
return $translator->trans('flarum-mentions.email.group_mentioned.subject', [
|
||||
'{mentioner_display_name}' => $this->post->user->display_name,
|
||||
'{title}' => $this->post->discussion->title
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getType()
|
||||
{
|
||||
return 'groupMentioned';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubjectModel()
|
||||
{
|
||||
return Post::class;
|
||||
}
|
||||
}
|
421
extensions/mentions/tests/integration/api/GroupMentionsTest.php
Normal file
421
extensions/mentions/tests/integration/api/GroupMentionsTest.php
Normal file
@@ -0,0 +1,421 @@
|
||||
<?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\Mentions\Tests\integration\api;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Flarum\Group\Group;
|
||||
use Flarum\Post\CommentPost;
|
||||
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
|
||||
use Flarum\Testing\integration\TestCase;
|
||||
use Flarum\User\User;
|
||||
|
||||
class GroupMentionsTest extends TestCase
|
||||
{
|
||||
use RetrievesAuthorizedUsers;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->extension('flarum-mentions');
|
||||
|
||||
$this->prepareDatabase([
|
||||
'users' => [
|
||||
['id' => 3, 'username' => 'potato', 'email' => 'potato@machine.local', 'is_email_confirmed' => 1],
|
||||
['id' => 4, 'username' => 'toby', 'email' => 'toby@machine.local', 'is_email_confirmed' => 1],
|
||||
['id' => 5, 'username' => 'bad_user', 'email' => 'bad_user@machine.local', 'is_email_confirmed' => 1],
|
||||
],
|
||||
'discussions' => [
|
||||
['id' => 2, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 3, 'first_post_id' => 4, 'comment_count' => 2],
|
||||
],
|
||||
'posts' => [
|
||||
['id' => 4, 'number' => 2, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 3, 'type' => 'comment', 'content' => '<r><p>One of the <GROUPMENTION color="#80349E" groupname="Mods" icon="fas fa-bolt" id="4">@"Mods"#g4</GROUPMENTION> will look at this</p></r>'],
|
||||
['id' => 6, 'number' => 3, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 3, 'type' => 'comment', 'content' => '<r><p><GROUPMENTION color="#80349E" groupname="OldGroupName" icon="fas fa-circle" id="100">@"OldGroupName"#g100</GROUPMENTION></p></r>'],
|
||||
['id' => 7, 'number' => 4, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 3, 'type' => 'comment', 'content' => '<r><p><GROUPMENTION color="#000" groupname="OldGroupName" icon="fas fa-circle" id="11">@"OldGroupName"#g11</GROUPMENTION></p></r>'],
|
||||
],
|
||||
'post_mentions_group' => [
|
||||
['post_id' => 4, 'mentions_group_id' => 4],
|
||||
['post_id' => 7, 'mentions_group_id' => 11],
|
||||
],
|
||||
'group_permission' => [
|
||||
['group_id' => Group::MEMBER_ID, 'permission' => 'postWithoutThrottle'],
|
||||
],
|
||||
'groups' => [
|
||||
[
|
||||
'id' => 10,
|
||||
'name_singular' => 'Hidden',
|
||||
'name_plural' => 'Ninjas',
|
||||
'color' => null,
|
||||
'icon' => 'fas fa-wrench',
|
||||
'is_hidden' => 1
|
||||
],
|
||||
[
|
||||
'id' => 11,
|
||||
'name_singular' => 'Fresh Name',
|
||||
'name_plural' => 'Fresh Name',
|
||||
'color' => '#ccc',
|
||||
'icon' => 'fas fa-users',
|
||||
'is_hidden' => 0
|
||||
]
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function rendering_a_valid_group_mention_works()
|
||||
{
|
||||
$response = $this->send(
|
||||
$this->request('GET', '/api/posts/4')
|
||||
);
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
|
||||
$response = json_decode($response->getBody(), true);
|
||||
|
||||
$this->assertStringContainsString('GroupMention', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertStringContainsString('#80349E', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertNotNull(CommentPost::find($response['data']['id'])->mentionsGroups->find(4));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function mentioning_an_invalid_group_doesnt_work()
|
||||
{
|
||||
$response = $this->send(
|
||||
$this->request('POST', '/api/posts', [
|
||||
'authenticatedAs' => 1,
|
||||
'json' => [
|
||||
'data' => [
|
||||
'attributes' => [
|
||||
'content' => '@"InvalidGroup"#g99',
|
||||
],
|
||||
'relationships' => [
|
||||
'discussion' => ['data' => ['id' => 2]],
|
||||
]
|
||||
],
|
||||
],
|
||||
])
|
||||
);
|
||||
|
||||
$this->assertEquals(201, $response->getStatusCode());
|
||||
|
||||
$response = json_decode($response->getBody(), true);
|
||||
|
||||
$this->assertStringContainsString('@"InvalidGroup"#g99', $response['data']['attributes']['content']);
|
||||
$this->assertStringNotContainsString('GroupMention', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertCount(0, CommentPost::find($response['data']['id'])->mentionsGroups);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function deleted_group_mentions_render_with_deleted_label()
|
||||
{
|
||||
$deleted_text = $this->app()->getContainer()->make('translator')->trans('flarum-mentions.forum.group_mention.deleted_text');
|
||||
|
||||
$response = $this->send(
|
||||
$this->request('GET', '/api/posts/6', [
|
||||
'authenticatedAs' => 1,
|
||||
])
|
||||
);
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
|
||||
$response = json_decode($response->getBody(), true);
|
||||
|
||||
$this->assertStringContainsString("@$deleted_text", $response['data']['attributes']['contentHtml']);
|
||||
$this->assertStringContainsString('GroupMention', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertStringContainsString('GroupMention--deleted', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertStringNotContainsString('@OldGroupName', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertCount(0, CommentPost::find($response['data']['id'])->mentionsGroups);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function group_mentions_render_with_fresh_data()
|
||||
{
|
||||
$response = $this->send(
|
||||
$this->request('GET', '/api/posts/7', [
|
||||
'authenticatedAs' => 1,
|
||||
])
|
||||
);
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
|
||||
$response = json_decode($response->getBody(), true);
|
||||
|
||||
$this->assertStringContainsString('@Fresh Name', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertStringContainsString('GroupMention', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertStringNotContainsString('@OldGroupName', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertNotNull(CommentPost::find($response['data']['id'])->mentionsGroups->find(11));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function mentioning_a_group_as_an_admin_user_works()
|
||||
{
|
||||
$response = $this->send(
|
||||
$this->request('POST', '/api/posts', [
|
||||
'authenticatedAs' => 1,
|
||||
'json' => [
|
||||
'data' => [
|
||||
'attributes' => [
|
||||
'content' => '@"Mods"#g4',
|
||||
],
|
||||
'relationships' => [
|
||||
'discussion' => ['data' => ['id' => 2]],
|
||||
]
|
||||
]
|
||||
]
|
||||
])
|
||||
);
|
||||
|
||||
$this->assertEquals(201, $response->getStatusCode());
|
||||
|
||||
$response = json_decode($response->getBody(), true);
|
||||
|
||||
$this->assertStringContainsString('@Mods', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertStringContainsString('fas fa-bolt', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertEquals('@"Mods"#g4', $response['data']['attributes']['content']);
|
||||
$this->assertStringContainsString('GroupMention', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertCount(1, CommentPost::find($response['data']['id'])->mentionsGroups);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function mentioning_multiple_groups_as_an_admin_user_works()
|
||||
{
|
||||
$response = $this->send(
|
||||
$this->request('POST', '/api/posts', [
|
||||
'authenticatedAs' => 1,
|
||||
'json' => [
|
||||
'data' => [
|
||||
'attributes' => [
|
||||
'content' => '@"Admins"#g1 @"Mods"#g4',
|
||||
],
|
||||
'relationships' => [
|
||||
'discussion' => ['data' => ['id' => 2]],
|
||||
]
|
||||
]
|
||||
]
|
||||
])
|
||||
);
|
||||
|
||||
$this->assertEquals(201, $response->getStatusCode());
|
||||
|
||||
$response = json_decode($response->getBody(), true);
|
||||
|
||||
$this->assertStringContainsString('@Admins', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertStringContainsString('@Mods', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertStringContainsString('fas fa-wrench', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertStringContainsString('fas fa-bolt', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertEquals('@"Admins"#g1 @"Mods"#g4', $response['data']['attributes']['content']);
|
||||
$this->assertStringContainsString('GroupMention', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertCount(2, CommentPost::find($response['data']['id'])->mentionsGroups);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function mentioning_a_virtual_group_as_an_admin_user_does_not_work()
|
||||
{
|
||||
$response = $this->send(
|
||||
$this->request('POST', '/api/posts', [
|
||||
'authenticatedAs' => 1,
|
||||
'json' => [
|
||||
'data' => [
|
||||
'attributes' => [
|
||||
'content' => '@"Members"#g3 @"Guests"#g2',
|
||||
],
|
||||
'relationships' => [
|
||||
'discussion' => ['data' => ['id' => 2]],
|
||||
]
|
||||
]
|
||||
]
|
||||
])
|
||||
);
|
||||
|
||||
$this->assertEquals(201, $response->getStatusCode());
|
||||
|
||||
$response = json_decode($response->getBody(), true);
|
||||
|
||||
$this->assertStringNotContainsString('@Members', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertStringNotContainsString('@Guests', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertEquals('@"Members"#g3 @"Guests"#g2', $response['data']['attributes']['content']);
|
||||
$this->assertStringNotContainsString('GroupMention', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertCount(0, CommentPost::find($response['data']['id'])->mentionsGroups);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function regular_user_does_not_have_group_mention_permission_by_default()
|
||||
{
|
||||
$this->database();
|
||||
$this->assertFalse(User::find(3)->can('mentionGroups'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function regular_user_does_have_group_mention_permission_when_added()
|
||||
{
|
||||
$this->prepareDatabase([
|
||||
'group_permission' => [
|
||||
['group_id' => Group::MEMBER_ID, 'permission' => 'mentionGroups'],
|
||||
]
|
||||
]);
|
||||
|
||||
$this->database();
|
||||
$this->assertTrue(User::find(3)->can('mentionGroups'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function user_without_permission_cannot_mention_groups()
|
||||
{
|
||||
$response = $this->send(
|
||||
$this->request('POST', '/api/posts', [
|
||||
'authenticatedAs' => 3,
|
||||
'json' => [
|
||||
'data' => [
|
||||
'attributes' => [
|
||||
'content' => '@"Mods"#g4',
|
||||
],
|
||||
'relationships' => [
|
||||
'discussion' => ['data' => ['id' => 2]],
|
||||
],
|
||||
],
|
||||
],
|
||||
])
|
||||
);
|
||||
|
||||
$this->assertEquals(201, $response->getStatusCode());
|
||||
|
||||
$response = json_decode($response->getBody(), true);
|
||||
|
||||
$this->assertStringNotContainsString('@Mods', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertStringContainsString('@"Mods"#g4', $response['data']['attributes']['content']);
|
||||
$this->assertStringNotContainsString('GroupMention', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertCount(0, CommentPost::find($response['data']['id'])->mentionsGroups);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function user_with_permission_can_mention_groups()
|
||||
{
|
||||
$this->prepareDatabase([
|
||||
'group_permission' => [
|
||||
['group_id' => Group::MEMBER_ID, 'permission' => 'mentionGroups'],
|
||||
]
|
||||
]);
|
||||
|
||||
$response = $this->send(
|
||||
$this->request('POST', '/api/posts', [
|
||||
'authenticatedAs' => 3,
|
||||
'json' => [
|
||||
'data' => [
|
||||
'attributes' => [
|
||||
'content' => '@"Mods"#g4',
|
||||
],
|
||||
'relationships' => [
|
||||
'discussion' => ['data' => ['id' => 2]],
|
||||
],
|
||||
],
|
||||
],
|
||||
])
|
||||
);
|
||||
|
||||
$this->assertEquals(201, $response->getStatusCode());
|
||||
|
||||
$response = json_decode($response->getBody(), true);
|
||||
|
||||
$this->assertStringContainsString('@Mods', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertStringContainsString('@"Mods"#g4', $response['data']['attributes']['content']);
|
||||
$this->assertStringContainsString('GroupMention', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertCount(1, CommentPost::find($response['data']['id'])->mentionsGroups);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function user_with_permission_cannot_mention_hidden_groups()
|
||||
{
|
||||
$this->prepareDatabase([
|
||||
'group_permission' => [
|
||||
['group_id' => Group::MEMBER_ID, 'permission' => 'mentionGroups'],
|
||||
]
|
||||
]);
|
||||
|
||||
$response = $this->send(
|
||||
$this->request('POST', '/api/posts', [
|
||||
'authenticatedAs' => 3,
|
||||
'json' => [
|
||||
'data' => [
|
||||
'attributes' => [
|
||||
'content' => '@"Ninjas"#g10',
|
||||
],
|
||||
'relationships' => [
|
||||
'discussion' => ['data' => ['id' => 2]],
|
||||
],
|
||||
],
|
||||
],
|
||||
])
|
||||
);
|
||||
|
||||
$this->assertEquals(201, $response->getStatusCode());
|
||||
|
||||
$response = json_decode($response->getBody(), true);
|
||||
|
||||
$this->assertStringNotContainsString('@Ninjas', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertStringContainsString('@"Ninjas"#g10', $response['data']['attributes']['content']);
|
||||
$this->assertStringNotContainsString('GroupMention', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertCount(0, CommentPost::find($response['data']['id'])->mentionsGroups);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function editing_a_post_that_has_a_mention_works()
|
||||
{
|
||||
$response = $this->send(
|
||||
$this->request('PATCH', '/api/posts/4', [
|
||||
'authenticatedAs' => 1,
|
||||
'json' => [
|
||||
'data' => [
|
||||
'attributes' => [
|
||||
'content' => 'New content with @"Mods"#g4 mention',
|
||||
],
|
||||
],
|
||||
],
|
||||
])
|
||||
);
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
|
||||
$response = json_decode($response->getBody(), true);
|
||||
|
||||
$this->assertStringContainsString('@Mods', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertEquals('New content with @"Mods"#g4 mention', $response['data']['attributes']['content']);
|
||||
$this->assertStringContainsString('GroupMention', $response['data']['attributes']['contentHtml']);
|
||||
$this->assertNotNull(CommentPost::find($response['data']['id'])->mentionsGroups->find(4));
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user