1
0
mirror of https://github.com/flarum/core.git synced 2025-08-14 12:24:33 +02:00

Compare commits

..

2 Commits

Author SHA1 Message Date
StyleCI Bot
b7c583b208 Apply fixes from StyleCI 2022-07-26 00:25:09 +00:00
Daniël Klabbers
01bdfcca33 wip 2022-07-26 02:24:56 +02:00
541 changed files with 13069 additions and 7323 deletions

View File

@@ -20,6 +20,3 @@ indent_size = 4
[tsconfig.json] [tsconfig.json]
indent_size = 2 indent_size = 2
[*.neon]
indent_style = tab

1
.github/CODEOWNERS vendored
View File

@@ -1 +0,0 @@
* @flarum/core

View File

@@ -9,12 +9,6 @@ on:
default: true default: true
required: false required: false
enable_phpstan:
description: "Enable PHPStan Static Analysis?"
type: boolean
default: false
required: false
backend_directory: 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. 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 type: string
@@ -25,19 +19,12 @@ on:
description: Versions of PHP to test with. Should be array of strings encoded as JSON array description: Versions of PHP to test with. Should be array of strings encoded as JSON array
type: string type: string
required: false required: false
default: '["7.3", "7.4", "8.0", "8.1"]' default: '["7.4", "8.0", "8.1"]'
php_extensions:
description: PHP extensions to install.
type: string
required: false
default: 'curl, dom, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip'
db_versions: db_versions:
description: Versions of databases to test with. Should be array of strings encoded as JSON array description: Versions of databases to test with. Should be array of strings encoded as JSON array
type: string type: string
required: false required: false
default: '["mysql:5.7", "mysql:8.0.30", "mariadb"]' default: '["mysql:5.7", "mariadb"]'
php_ini_values: php_ini_values:
description: PHP ini values description: PHP ini values
@@ -57,41 +44,23 @@ jobs:
matrix: matrix:
php: ${{ fromJSON(inputs.php_versions) }} php: ${{ fromJSON(inputs.php_versions) }}
service: ${{ fromJSON(inputs.db_versions) }} service: ${{ fromJSON(inputs.db_versions) }}
prefix: [''] prefix: ['', flarum_]
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixinclude
include: include:
# Expands the matrix by naming DBs.
- service: 'mysql:5.7' - service: 'mysql:5.7'
db: MySQL 5.7 db: MySQL
- service: 'mysql:8.0.30'
db: MySQL 8.0
- service: mariadb - service: mariadb
db: MariaDB db: MariaDB
- prefix: flarum_
# Include Database prefix tests with only one PHP version.
- php: ${{ fromJSON(inputs.php_versions)[0] }}
service: 'mysql:5.7'
db: MySQL 5.7
prefix: flarum_
prefixStr: (prefix)
- php: ${{ fromJSON(inputs.php_versions)[0] }}
service: 'mysql:8.0.30'
db: MySQL 8.0
prefix: flarum_
prefixStr: (prefix)
- php: ${{ fromJSON(inputs.php_versions)[0] }}
service: mariadb
db: MariaDB
prefix: flarum_
prefixStr: (prefix) prefixStr: (prefix)
# To reduce number of actions, we exclude some PHP versions from running with some DB versions.
exclude: exclude:
- php: ${{ fromJSON(inputs.php_versions)[1] }} - php: 8.0
service: 'mysql:8.0.30' service: 'mysql:5.7'
- php: ${{ fromJSON(inputs.php_versions)[2] }} prefix: flarum_
service: 'mysql:8.0.30' - php: 8.0
service: mariadb
prefix: flarum_
services: services:
mysql: mysql:
@@ -101,9 +70,7 @@ jobs:
name: 'PHP ${{ matrix.php }} / ${{ matrix.db }} ${{ matrix.prefixStr }}' name: 'PHP ${{ matrix.php }} / ${{ matrix.db }} ${{ matrix.prefixStr }}'
if: >- if: inputs.enable_backend_testing
inputs.enable_backend_testing &&
((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || github.event_name != 'pull_request')
steps: steps:
- uses: actions/checkout@master - uses: actions/checkout@master
@@ -113,7 +80,7 @@ jobs:
with: with:
php-version: ${{ matrix.php }} php-version: ${{ matrix.php }}
coverage: xdebug coverage: xdebug
extensions: ${{ inputs.php_extensions }} extensions: curl, dom, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip
tools: phpunit, composer:v2 tools: phpunit, composer:v2
ini-values: ${{ inputs.php_ini_values }} ini-values: ${{ inputs.php_ini_values }}
@@ -143,35 +110,3 @@ jobs:
working-directory: ${{ inputs.backend_directory }} working-directory: ${{ inputs.backend_directory }}
env: env:
COMPOSER_PROCESS_TIMEOUT: 600 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: ${{ inputs.php_ini_values }}
- name: Install Composer dependencies
run: composer install
working-directory: ${{ inputs.backend_directory }}
- name: Run PHPStan
run: composer analyse:phpstan

View File

@@ -3,32 +3,6 @@ name: Flarum Frontend Jobs
on: on:
workflow_call: workflow_call:
inputs: inputs:
build_script:
description: "Script to run for production build. Empty value to disable."
type: string
required: false
default: build
build_typings_script:
description: "Script to run for typings build. Empty value to disable."
type: string
required: false
default: build-typings
format_script:
description: "Script to run for code formatting. Empty value to disable."
type: string
required: false
default: format-check
check_typings_script:
description: "Script to run for tyiping check. Empty value to disable."
type: string
required: false
default: check-typings
type_coverage_script:
description: "Script to run for type coverage. Empty value to disable."
type: string
required: false
default: check-typings-coverage
enable_bundlewatch: enable_bundlewatch:
description: "Enable Bundlewatch?" description: "Enable Bundlewatch?"
type: boolean type: boolean
@@ -87,12 +61,66 @@ env:
cache_dependency_path: ${{ inputs.cache_dependency_path || format(inputs.js_package_manager == 'yarn' && '{0}/yarn.lock' || '{0}/package-lock.json', inputs.frontend_directory) }} cache_dependency_path: ${{ inputs.cache_dependency_path || format(inputs.js_package_manager == 'yarn' && '{0}/yarn.lock' || '{0}/package-lock.json', inputs.frontend_directory) }}
jobs: jobs:
build: bundlewatch:
name: Checks & Build name: Bundlewatch
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: inputs.enable_bundlewatch
if: >- steps:
((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || github.event_name != 'pull_request') - name: Check out code
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: ${{ inputs.node_version }}
cache: ${{ inputs.js_package_manager }}
cache-dependency-path: ${{ env.cache_dependency_path }}
- name: Build production assets
uses: flarum/action-build@2
with:
github_token: ${{ secrets.github_token }}
build_script: build
package_manager: ${{ inputs.js_package_manager }}
js_path: ${{ inputs.frontend_directory }}
do_not_commit: true
- name: Check bundle size change
run: node_modules/.bin/bundlewatch --config .bundlewatch.config.json
working-directory: ${{ inputs.frontend_directory }}
env:
BUNDLEWATCH_GITHUB_TOKEN: ${{ secrets.bundlewatch_github_token }}
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
prettier:
name: Prettier
runs-on: ubuntu-latest
if: inputs.enable_prettier
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: ${{ inputs.node_version }}
cache: ${{ inputs.js_package_manager }}
cache-dependency-path: ${{ env.cache_dependency_path }}
- name: Install JS dependencies
run: ${{ env.ci_script }}
working-directory: ${{ inputs.frontend_directory }}
- name: Check JS formatting
run: ${{ inputs.js_package_manager }} run format-check
working-directory: ${{ inputs.frontend_directory }}
typecheck:
name: Typecheck
runs-on: ubuntu-latest
if: inputs.enable_typescript
steps: steps:
- name: Check out code - name: Check out code
@@ -121,23 +149,72 @@ jobs:
run: ${{ env.ci_script }} run: ${{ env.ci_script }}
working-directory: ${{ inputs.frontend_directory }} working-directory: ${{ inputs.frontend_directory }}
- name: JS Checks & Production Build - name: Typecheck
uses: flarum/action-build@3 run: ${{ inputs.js_package_manager }} run check-typings
working-directory: ${{ inputs.frontend_directory }}
type-coverage:
name: Type Coverage
runs-on: ubuntu-latest
if: inputs.enable_typescript
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: ${{ inputs.node_version }}
cache: ${{ inputs.js_package_manager }}
cache-dependency-path: ${{ env.cache_dependency_path }}
- name: Install JS dependencies
run: ${{ env.ci_script }}
working-directory: ${{ inputs.frontend_directory }}
- name: Check type coverage
run: ${{ inputs.js_package_manager }} run check-typings-coverage
working-directory: ${{ inputs.frontend_directory }}
build:
name: Build
runs-on: ubuntu-latest
if: "always() && !contains(needs.*.result, 'failed') && !contains(needs.*.result, 'cancelled')"
needs: [bundlewatch, prettier, typecheck, type-coverage]
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: ${{ inputs.node_version }}
cache: ${{ inputs.js_package_manager }}
cache-dependency-path: ${{ env.cache_dependency_path }}
# Our action will install npm/yarn, cd into `${{ inputs.frontend_directory }}`, build dist JS and typings,
# then commit and upload any changes iff we are on the main branch and have just pushed.
- name: Build production JS
if: inputs.enable_typescript
uses: flarum/action-build@2
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
build_script: ${{ inputs.build_script }} build_script: build
build_typings_script: ${{ inputs.build_typings_script }}
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 || '' }}
package_manager: ${{ inputs.js_package_manager }} package_manager: ${{ inputs.js_package_manager }}
typings_script: build-typings
js_path: ${{ inputs.frontend_directory }} js_path: ${{ inputs.frontend_directory }}
do_not_commit: ${{ github.ref != format('refs/heads/{0}', inputs.main_git_branch) || github.event_name != 'push' }} do_not_commit: ${{ github.ref != format('refs/heads/{0}', inputs.main_git_branch) || github.event_name != 'push' }}
- name: Check bundle size change # Our action will install npm/yarn, cd into `${{ inputs.frontend_directory }}`, build dist JS and typings,
if: ${{ inputs.enable_bundlewatch }} # then commit and upload any changes iff we are on the main branch and have just pushed.
run: node_modules/.bin/bundlewatch --config .bundlewatch.config.json - name: Build production JS
working-directory: ${{ inputs.frontend_directory }} if: "! inputs.enable_typescript"
env: uses: flarum/action-build@2
BUNDLEWATCH_GITHUB_TOKEN: ${{ secrets.bundlewatch_github_token }} with:
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }} github_token: ${{ secrets.GITHUB_TOKEN }}
build_script: build
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' }}

20
.github/workflows/flarum-akismet-frontend.yml vendored Executable file
View File

@@ -0,0 +1,20 @@
name: Akismet JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: true
frontend_directory: ./extensions/akismet/js
backend_directory: ./extensions/akismet
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

View File

@@ -0,0 +1,20 @@
name: Approval JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: false
frontend_directory: ./extensions/approval/js
backend_directory: ./extensions/approval
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

View File

@@ -1,4 +1,4 @@
name: Framework JS name: Core JS
on: [workflow_dispatch, push, pull_request] on: [workflow_dispatch, push, pull_request]
@@ -6,8 +6,12 @@ jobs:
run: run:
uses: ./.github/workflows/REUSABLE_frontend.yml uses: ./.github/workflows/REUSABLE_frontend.yml
with: with:
frontend_directory: ./ enable_bundlewatch: true
backend_directory: ./ enable_prettier: true
enable_typescript: true
frontend_directory: ./framework/core/js
backend_directory: ./framework/core
js_package_manager: yarn js_package_manager: yarn
cache_dependency_path: ./yarn.lock cache_dependency_path: ./yarn.lock
main_git_branch: main main_git_branch: main

20
.github/workflows/flarum-embed-frontend.yml vendored Executable file
View File

@@ -0,0 +1,20 @@
name: Embed JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: false
frontend_directory: ./extensions/embed/js
backend_directory: ./extensions/embed
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

20
.github/workflows/flarum-emoji-frontend.yml vendored Executable file
View File

@@ -0,0 +1,20 @@
name: Emoji JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: false
frontend_directory: ./extensions/emoji/js
backend_directory: ./extensions/emoji
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

20
.github/workflows/flarum-flags-frontend.yml vendored Executable file
View File

@@ -0,0 +1,20 @@
name: Flags JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: true
frontend_directory: ./extensions/flags/js
backend_directory: ./extensions/flags
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

20
.github/workflows/flarum-likes-frontend.yml vendored Executable file
View File

@@ -0,0 +1,20 @@
name: Likes JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: false
frontend_directory: ./extensions/likes/js
backend_directory: ./extensions/likes
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

20
.github/workflows/flarum-lock-frontend.yml vendored Executable file
View File

@@ -0,0 +1,20 @@
name: Lock JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: false
frontend_directory: ./extensions/lock/js
backend_directory: ./extensions/lock
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

View File

@@ -0,0 +1,20 @@
name: Markdown JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: false
frontend_directory: ./extensions/markdown/js
backend_directory: ./extensions/markdown
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

View File

@@ -0,0 +1,20 @@
name: Mentions JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: false
frontend_directory: ./extensions/mentions/js
backend_directory: ./extensions/mentions
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

View File

@@ -0,0 +1,20 @@
name: Nicknames JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: false
frontend_directory: ./extensions/nicknames/js
backend_directory: ./extensions/nicknames
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

View File

@@ -0,0 +1,20 @@
name: Package Manager JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: true
frontend_directory: ./extensions/package-manager/js
backend_directory: ./extensions/package-manager
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

20
.github/workflows/flarum-pusher-frontend.yml vendored Executable file
View File

@@ -0,0 +1,20 @@
name: Pusher JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: true
frontend_directory: ./extensions/pusher/js
backend_directory: ./extensions/pusher
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

View File

@@ -0,0 +1,20 @@
name: Statistics JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: true
frontend_directory: ./extensions/statistics/js
backend_directory: ./extensions/statistics
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

20
.github/workflows/flarum-sticky-frontend.yml vendored Executable file
View File

@@ -0,0 +1,20 @@
name: Sticky JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: false
frontend_directory: ./extensions/sticky/js
backend_directory: ./extensions/sticky
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

View File

@@ -0,0 +1,20 @@
name: Subscriptions JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: false
frontend_directory: ./extensions/subscriptions/js
backend_directory: ./extensions/subscriptions
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

20
.github/workflows/flarum-suspend-frontend.yml vendored Executable file
View File

@@ -0,0 +1,20 @@
name: Suspend JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: false
frontend_directory: ./extensions/suspend/js
backend_directory: ./extensions/suspend
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

19
.github/workflows/flarum-tags-frontend.yml vendored Executable file
View File

@@ -0,0 +1,19 @@
name: Tags JS
on: [workflow_dispatch, push, pull_request]
jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
with:
enable_bundlewatch: false
enable_prettier: true
enable_typescript: true
frontend_directory: ./extensions/tags/js
backend_directory: ./extensions/tags
js_package_manager: yarn
cache_dependency_path: ./yarn.lock
main_git_branch: main
secrets:
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}

View File

@@ -1,12 +0,0 @@
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: .

View File

@@ -1,26 +0,0 @@
name: Prepare Release
on:
workflow_dispatch:
inputs:
version:
description: 'Version to release'
required: true
type: string
jobs:
run:
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
pull-requests: read
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Prepare release
uses: flarum/action-release@master
env:
NEXT_TAG: ${{ inputs.version }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPEN_COLLECTIVE_TOKEN: ${{ secrets.OPEN_COLLECTIVE_TOKEN }}

View File

@@ -1,124 +1,5 @@
# Changelog # Changelog
## [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]
- (a11y) present post streams as feeds [#3522]
- (a11y) set `aria-busy` when editing a post stream item [#3521]
- (compilation) versioner not inject into compilers [#3589]
- (mentions) accessing `id` of null `user` relation [#3618]
- (subscriptions) add missing table prefix for filter gambit [#3599]
- (tags) use default index sortmap [#3615]
- Move guzzle requirement to core [#3544]
- MyISAM tables for extensions during installation ([75aaef7](75aaef7d76317bc8578eac1439fed8091c87213b), [f926c58](f926c58e0143fe75a4a4c2e93810970c5910afc8))
- Set the translator locale to user preference for email notifications [#3525]
- `$events` property declared dynamically [#3598]
- core settings header has no priority ([33bf228](33bf2284c77863a1bb18d71d87b8516483056a74))
- html entities shown raw in page title [#3542]
- incorrect centring of deleted user avatars in notification list [#3569]
- intellisense imports defaulting to absolute path from `src` folder [#3549]
- minor backward compatible fix for php 8.1 in st_replace ([07b2f86](07b2f86dcc90a3ef17c8ee19a1a07e99a4b17360))
- post query wildcard selection causes ambiguity [#3621]
- potential static caching memory exhaustion [#3548]
- prepare release workflow has invalid layout ([70e483d](70e483d1b185332910be9513fd06cc6342830d49))
- remove deprecation warning for decoding null values ([590639f](590639f5f3e1fe883f28c41e1f175c2826b4b5f4))
- replace `.fa()` mixin usage with `.fas()` [#3537]
- return type hint static is php 8+ ([b01b75e](b01b75e36790d8026dd27ce59051d9581ad47940))
- sticky nav content displays below post stream [#3575]
- titles positioned wrongly with custom header height [#3550]
- typo in error message ([1a189f4](1a189f492320071365286a8835bc49d5a9571753))
- unread notifications are globally cached between users. [#3543]
- update workflow name ([628c281](628c281c39855f01069ddc40b698d80d29fec870))
- user has wrong discussion read status [#3591]
### Changed
- (approval, likes) use subscribers [#3577]
- (package-manager) last tweaks before beta tag ([335c602](335c602cea3fbaee9ad7c32ceecaaf222e5d89a7))
- (statistics) add release notes for 1.4.1 ([f4ace73](f4ace73a3c59434b8717efb2d83f50084f470fe4))
- (statistics) rewrite for performance on very large communities [#3531]
- (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]
- Create CODEOWNERS ([6e48a03](6e48a0303e45bcf210e550ba3e0772bc8443a207))
- MyISAM tables for extensions during installation" ([f128190](f128190f143398dd1262fd1379e634794daee4c1))
- convert `AlertManager` `IndexPage` and `UserPage` components to TS [#3536]
- convert `Badge` `Checkbox` and `Navigation` components to TS [#3532]
- convert core modals to TypeScript [#3515]
- convert page components to TypeScript [#3538]
- debug line slipped in while rebasing a PR [#3580]
- don't pass password field between auth modals [#3626]
- fix github issue templates ([d3e456a](d3e456a1bf42d13b7cd2542c371f392712247c09))
- format code ([4954621](495462183bfb3b33046b293e6b1088ab225968df))
- getting the release workflow in ([5530400](5530400b093b5fd07d670e5c92d8a7da96634cfe))
- link logo at the top with the official website [#3552]
- prevent running both `push` and `pull_request` actions at the same time [#3597]
- refactor prefix matrix and add `MySQL 8.0` & `PHP 7.3` to workflows [#3595]
- relying on a third-party for avatar URL tests is unreliable [#3586]
- require guzzle 6 or 7 ([46b3b7a](46b3b7a9527b935c3c52269aaad2010c75dcb6d8))
- split FA imports into separate Less file for easy overriding [#3535]
- unify JS actions into one (rewritten `flarum/action-build`) [#3573]
- update version constant during cycle 22 ([d864405](d86440506dd37101e60adec591d4b017e7765ec6))
- use `isCollapsed` instead of `rangeCount` [#3581]
- use github issue template forms [#3526]
### Added
- (likes) Add likes tab to user profile [#3528]
- (likes) Option to prevent users liking their own posts [#3534]
- (modals) support stacking modals, remove bootstrap modals dependency [#3456]
- (subscriptions) add option to send notifications when not caught up [#3503]
- Add custom class for email confirmation alert [#3584]
- Admin debug mode warning [#3590]
- Delete all notifications [#3529]
- Queue package manager commands [#3418]
- Restart the queue worker after cache clearing, ext enable/disable, save settings [#3565]
- add createTableIfNotExists migration helper [#3576]
- add new workflow for generating release meta ([0901e59](0901e59a58a3e1f017762583a2adf419f7f34257))
- clear password & email tokens when appropriate [#3567]
- discussion UTF-8 slug driver [#3606]
- expose assets base url to frontend forum model [#3566]
- extender to add custom less variables [#3530]
- publish assets on admin dashboard cache clear [#3564]
- throttle email change, email confirmation, and password reset endpoints. [#3555]
## [1.4.0](https://github.com/flarum/framework/compare/v1.3.1...v1.4.0) ## [1.4.0](https://github.com/flarum/framework/compare/v1.3.1...v1.4.0)
### Added ### Added

View File

@@ -1,6 +1,4 @@
<p align="center"> <p align="center"><img src="https://flarum.org/assets/img/logo.png"></p>
<a href="https://flarum.org/"><img src="https://flarum.org/assets/img/logo.png"></a>
</p>
<p align="center"> <p align="center">
<a href="https://github.com/flarum/core/actions?query=workflow%3ATests"><img src="https://github.com/flarum/core/workflows/Tests/badge.svg" alt="PHP Tests"></a> <a href="https://github.com/flarum/core/actions?query=workflow%3ATests"><img src="https://github.com/flarum/core/workflows/Tests/badge.svg" alt="PHP Tests"></a>

View File

@@ -140,8 +140,8 @@
"require-dev": { "require-dev": {
"mockery/mockery": "^1.4", "mockery/mockery": "^1.4",
"phpunit/phpunit": "^9.0", "phpunit/phpunit": "^9.0",
"phpstan/phpstan": ">=1.8.11 < 1.9.0", "phpstan/phpstan-php-parser": "^1.0",
"nunomaduro/larastan": "^1.0" "phpstan/phpstan": "^1.2"
}, },
"config": { "config": {
"sort-packages": true "sort-packages": true
@@ -178,11 +178,5 @@
"extension.neon" "extension.neon"
] ]
} }
},
"scripts": {
"analyse:phpstan": "phpstan analyse"
},
"scripts-descriptions": {
"analyse:phpstan": "Run static analysis"
} }
} }

View File

@@ -19,7 +19,7 @@
} }
], ],
"require": { "require": {
"flarum/core": "^1.6", "flarum/core": "^1.4",
"flarum/approval": "^1.2" "flarum/approval": "^1.2"
}, },
"autoload": { "autoload": {

View File

@@ -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,GCLRF,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,MCJ3ER,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,M,+BCLvD,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,a","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":""}

View File

@@ -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,GCLRF,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,MCJ3ER,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,M,+BCLvD,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,WAAuB,CAC7D,IAAMC,EAAcP,EAAMf,IAAI,WAC1BsB,GAAsC,iBAAhBA,GAA4B,aAAcA,IAClEA,EAAYC,SAAWX,IAAAA,WAAAA,MAAqB,oDAMpDY,EAAAA,EAAAA,UAASC,IAAAA,UAAuB,cAAc,SAAUC,EAAUN,GAChE,MAAoB,YAAhBA,EAAKC,OACAT,IAAAA,WAAAA,MAAqB,kDAGvBc,EAASN,U","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":""}

View File

@@ -9,11 +9,11 @@
"analyze": "cross-env ANALYZER=true yarn run build", "analyze": "cross-env ANALYZER=true yarn run build",
"format": "prettier --write src", "format": "prettier --write src",
"format-check": "prettier --check src", "format-check": "prettier --check src",
"check-typings": "tsc --noEmit --emitDeclarationOnly false",
"check-typings-coverage": "typescript-coverage-report",
"clean-typings": "npx rimraf dist-typings && mkdir dist-typings", "clean-typings": "npx rimraf dist-typings && mkdir dist-typings",
"build-typings": "yarn run clean-typings && ([ -e src/@types ] && cp -r src/@types dist-typings/@types || true) && tsc && yarn run post-build-typings", "build-typings": "yarn run clean-typings && ([ -e src/@types ] && cp -r src/@types dist-typings/@types || true) && tsc && yarn run post-build-typings",
"post-build-typings": "find dist-typings -type f -name '*.d.ts' -print0 | xargs -0 sed -i 's,../src/@types,@types,g'", "post-build-typings": "find dist-typings -type f -name '*.d.ts' -print0 | xargs -0 sed -i 's,../src/@types,@types,g'"
"check-typings": "tsc --noEmit --emitDeclarationOnly false",
"check-typings-coverage": "typescript-coverage-report"
}, },
"devDependencies": { "devDependencies": {
"@flarum/prettier-config": "^1.0.0", "@flarum/prettier-config": "^1.0.0",

View File

@@ -4,18 +4,14 @@
// This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder // 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 // and also tells your Typescript server to read core's global typings for
// access to `dayjs` and `$` in the global namespace. // access to `dayjs` and `$` in the global namespace.
"include": [ "include": ["src/**/*", "../vendor/*/*/js/dist-typings/@types/**/*", "@types/**/*"],
"src/**/*",
"../../../framework/core/js/dist-typings/@types/**/*",
"../../flags/js/dist-typings/@types/**/*",
"@types/**/*"
],
"compilerOptions": { "compilerOptions": {
// This will output typings to `dist-typings` // This will output typings to `dist-typings`
"declarationDir": "./dist-typings", "declarationDir": "./dist-typings",
"baseUrl": ".",
"paths": { "paths": {
"flarum/*": ["../../../framework/core/js/dist-typings/*"], "flarum/*": ["../vendor/flarum/core/js/dist-typings/*"],
"flarum/flags/*": ["../../flags/js/dist-typings/*"] "flarum/flags/*": ["../vendor/flarum/flags/js/dist-typings/*"]
} }
} }
} }

View File

@@ -38,7 +38,7 @@ class AkismetProvider extends AbstractServiceProvider
$settings->get('flarum-akismet.api_key'), $settings->get('flarum-akismet.api_key'),
$url->to('forum')->base(), $url->to('forum')->base(),
$app::VERSION, $app::VERSION,
$extensions->getExtension('flarum-akismet')->getVersion() ?? 'unknown', $extensions->getExtension('flarum-akismet')->getVersion(),
$config->inDebugMode() $config->inDebugMode()
); );
}); });

View File

@@ -19,7 +19,7 @@
} }
], ],
"require": { "require": {
"flarum/core": "^1.6", "flarum/core": "^1.4",
"flarum/flags": "^1.2" "flarum/flags": "^1.2"
}, },
"autoload": { "autoload": {

View File

@@ -15,6 +15,7 @@ use Flarum\Approval\Listener;
use Flarum\Discussion\Discussion; use Flarum\Discussion\Discussion;
use Flarum\Extend; use Flarum\Extend;
use Flarum\Post\CommentPost; use Flarum\Post\CommentPost;
use Flarum\Post\Event\Saving;
use Flarum\Post\Post; use Flarum\Post\Post;
use Flarum\Tags\Tag; use Flarum\Tags\Tag;
@@ -49,9 +50,9 @@ return [
new Extend\Locales(__DIR__.'/locale'), new Extend\Locales(__DIR__.'/locale'),
(new Extend\Event()) (new Extend\Event())
->listen(PostWasApproved::class, Listener\UpdateDiscussionAfterPostApproval::class) ->listen(Saving::class, [Listener\ApproveContent::class, 'approvePost'])
->subscribe(Listener\ApproveContent::class) ->listen(Saving::class, [Listener\UnapproveNewContent::class, 'unapproveNewPosts'])
->subscribe(Listener\UnapproveNewContent::class), ->listen(PostWasApproved::class, [Listener\ApproveContent::class, 'approveDiscussion']),
(new Extend\Policy()) (new Extend\Policy())
->modelPolicy(Tag::class, Access\TagPolicy::class), ->modelPolicy(Tag::class, Access\TagPolicy::class),

View File

@@ -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,GCLRF,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,MCJ3ER,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,M,+BCLvD,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,uBAIlBJ,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,Q","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":""}

File diff suppressed because one or more lines are too long

View File

@@ -11,19 +11,13 @@ namespace Flarum\Approval\Listener;
use Flarum\Approval\Event\PostWasApproved; use Flarum\Approval\Event\PostWasApproved;
use Flarum\Post\Event\Saving; use Flarum\Post\Event\Saving;
use Illuminate\Contracts\Events\Dispatcher;
class ApproveContent class ApproveContent
{ {
/** /**
* @param Dispatcher $events * @param Saving $event
*/ */
public function subscribe(Dispatcher $events) public static function approvePost(Saving $event)
{
$events->listen(Saving::class, [$this, 'approvePost']);
}
public function approvePost(Saving $event)
{ {
$attributes = $event->data['attributes']; $attributes = $event->data['attributes'];
$post = $event->post; $post = $event->post;
@@ -42,4 +36,30 @@ class ApproveContent
$post->raise(new PostWasApproved($post, $event->actor)); $post->raise(new PostWasApproved($post, $event->actor));
} }
} }
/**
* @param PostWasApproved $event
*/
public static 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();
}
} }

View File

@@ -13,22 +13,13 @@ use Flarum\Discussion\Discussion;
use Flarum\Flags\Flag; use Flarum\Flags\Flag;
use Flarum\Post\CommentPost; use Flarum\Post\CommentPost;
use Flarum\Post\Event\Saving; use Flarum\Post\Event\Saving;
use Illuminate\Contracts\Events\Dispatcher;
class UnapproveNewContent class UnapproveNewContent
{ {
/**
* @param Dispatcher $events
*/
public function subscribe(Dispatcher $events)
{
$events->listen(Saving::class, [$this, 'unapproveNewPosts']);
}
/** /**
* @param Saving $event * @param Saving $event
*/ */
public function unapproveNewPosts(Saving $event) public static function unapproveNewPosts(Saving $event)
{ {
$post = $event->post; $post = $event->post;

View File

@@ -1,40 +0,0 @@
<?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();
}
}
}

View File

@@ -19,7 +19,7 @@
} }
], ],
"require": { "require": {
"flarum/core": "^1.6" "flarum/core": "^1.4"
}, },
"extra": { "extra": {
"branch-alias": { "branch-alias": {

View File

@@ -19,7 +19,7 @@
} }
], ],
"require": { "require": {
"flarum/core": "^1.6" "flarum/core": "^1.4"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

File diff suppressed because one or more lines are too long

View File

@@ -19,7 +19,7 @@
} }
], ],
"require": { "require": {
"flarum/core": "^1.6" "flarum/core": "^1.4"
}, },
"extra": { "extra": {
"branch-alias": { "branch-alias": {

File diff suppressed because one or more lines are too long

View File

@@ -22,6 +22,10 @@
"build": "webpack --mode production", "build": "webpack --mode production",
"format": "prettier --write src", "format": "prettier --write src",
"format-check": "prettier --check src", "format-check": "prettier --check src",
"analyze": "cross-env ANALYZER=true yarn run build" "analyze": "cross-env ANALYZER=true yarn run build",
"clean-typings": "npx rimraf dist-typings && mkdir dist-typings",
"build-typings": "npm run clean-typings && cp -r src/@types dist-typings/@types && tsc",
"check-typings": "tsc --noEmit --emitDeclarationOnly false",
"check-typings-coverage": "typescript-coverage-report"
} }
} }

View File

@@ -19,7 +19,7 @@
} }
], ],
"require": { "require": {
"flarum/core": "^1.6" "flarum/core": "^1.4"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

View File

@@ -1,7 +1,5 @@
export default class FlagList extends Component<import("flarum/common/Component").ComponentAttrs, undefined> { export default class FlagList {
constructor();
oninit(vnode: any): void; oninit(vnode: any): void;
state: any; state: any;
view(): JSX.Element; view(): JSX.Element;
} }
import Component from "flarum/common/Component";

View File

@@ -1,15 +1,12 @@
/// <reference types="flarum/@types/translator-icu-rich" /> export default class FlagPostModal {
export default class FlagPostModal extends Modal<import("flarum/common/components/Modal").IInternalModalAttrs> {
constructor();
oninit(vnode: any): void; oninit(vnode: any): void;
success: boolean | undefined; success: boolean | undefined;
reason: Stream<string> | undefined; reason: any;
reasonDetail: Stream<string> | undefined; reasonDetail: any;
title(): import("@askvortsov/rich-icu-message-formatter").NestedStringArray; className(): string;
title(): any;
content(): JSX.Element; content(): JSX.Element;
flagReasons(): ItemList<any>; flagReasons(): any;
onsubmit(e: any): void; onsubmit(e: any): void;
loading: boolean | undefined;
} }
import Modal from "flarum/common/components/Modal";
import Stream from "flarum/common/utils/Stream";
import ItemList from "flarum/common/utils/ItemList";

View File

@@ -3,5 +3,5 @@ export default class FlagsDropdown {
getMenu(): JSX.Element; getMenu(): JSX.Element;
goToRoute(): void; goToRoute(): void;
getUnreadCount(): any; getUnreadCount(): any;
getNewCount(): unknown; getNewCount(): any;
} }

View File

@@ -1,11 +1,9 @@
import Model from 'flarum/common/Model'; import Model from 'flarum/common/Model';
import type Post from 'flarum/common/models/Post';
import type User from 'flarum/common/models/User';
export default class Flag extends Model { export default class Flag extends Model {
type(): string; type(): any;
reason(): string | null; reason(): any;
reasonDetail(): string | null; reasonDetail(): any;
createdAt(): Date | null | undefined; createdAt(): any;
post(): false | Post; post(): any;
user(): false | User | null; user(): any;
} }

View File

@@ -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,GCLRF,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,MCJ3ER,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,M,+BCLvD,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,Q","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":""}

File diff suppressed because one or more lines are too long

View File

@@ -17,13 +17,13 @@
"scripts": { "scripts": {
"dev": "webpack --mode development --watch", "dev": "webpack --mode development --watch",
"build": "webpack --mode production", "build": "webpack --mode production",
"analyze": "cross-env ANALYZER=true yarn run build",
"format": "prettier --write src", "format": "prettier --write src",
"format-check": "prettier --check src", "format-check": "prettier --check src",
"analyze": "cross-env ANALYZER=true yarn run build",
"clean-typings": "npx rimraf dist-typings && mkdir dist-typings", "clean-typings": "npx rimraf dist-typings && mkdir dist-typings",
"build-typings": "yarn run clean-typings && ([ -e src/@types ] && cp -r src/@types dist-typings/@types || true) && tsc && yarn run post-build-typings", "build-typings": "yarn run clean-typings && ([ -e src/@types ] && cp -r src/@types dist-typings/@types || true) && tsc && yarn run post-build-typings",
"post-build-typings": "find dist-typings -type f -name '*.d.ts' -print0 | xargs -0 sed -i 's,../src/@types,@types,g'",
"check-typings": "tsc --noEmit --emitDeclarationOnly false", "check-typings": "tsc --noEmit --emitDeclarationOnly false",
"check-typings-coverage": "typescript-coverage-report" "check-typings-coverage": "typescript-coverage-report",
"post-build-typings": "find dist-typings -type f -name '*.d.ts' -print0 | xargs -0 sed -i 's,../src/@types,@types,g'"
} }
} }

View File

@@ -4,13 +4,14 @@
// This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder // 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 // and also tells your Typescript server to read core's global typings for
// access to `dayjs` and `$` in the global namespace. // access to `dayjs` and `$` in the global namespace.
"include": ["src/**/*", "../../../*/*/js/dist-typings/@types/**/*", "@types/**/*"], "include": ["src/**/*", "../vendor/*/*/js/dist-typings/@types/**/*", "@types/**/*"],
"compilerOptions": { "compilerOptions": {
// This will output typings to `dist-typings` // This will output typings to `dist-typings`
"declarationDir": "./dist-typings", "declarationDir": "./dist-typings",
"baseUrl": ".",
"paths": { "paths": {
"flarum/*": ["../../../framework/core/js/dist-typings/*"], "flarum/*": ["../vendor/flarum/core/js/dist-typings/*"],
"@flarum/core/*": ["../../../framework/core/js/dist-typings/*"] "@flarum/core/*": ["../vendor/flarum/core/js/dist-typings/*"]
} }
} }
} }

View File

@@ -7,7 +7,7 @@
], ],
"license": "MIT", "license": "MIT",
"require": { "require": {
"flarum/core": "^1.6" "flarum/core": "^1.4"
}, },
"extra": { "extra": {
"branch-alias": { "branch-alias": {

View File

@@ -19,7 +19,7 @@
} }
], ],
"require": { "require": {
"flarum/core": "^1.6" "flarum/core": "^1.4"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

View File

@@ -17,6 +17,8 @@ use Flarum\Likes\Event\PostWasLiked;
use Flarum\Likes\Event\PostWasUnliked; use Flarum\Likes\Event\PostWasUnliked;
use Flarum\Likes\Notification\PostLikedBlueprint; use Flarum\Likes\Notification\PostLikedBlueprint;
use Flarum\Likes\Query\LikedByFilter; use Flarum\Likes\Query\LikedByFilter;
use Flarum\Post\Event\Deleted;
use Flarum\Post\Event\Saving;
use Flarum\Post\Filter\PostFilterer; use Flarum\Post\Filter\PostFilterer;
use Flarum\Post\Post; use Flarum\Post\Post;
use Flarum\User\User; use Flarum\User\User;
@@ -58,7 +60,8 @@ return [
(new Extend\Event()) (new Extend\Event())
->listen(PostWasLiked::class, Listener\SendNotificationWhenPostIsLiked::class) ->listen(PostWasLiked::class, Listener\SendNotificationWhenPostIsLiked::class)
->listen(PostWasUnliked::class, Listener\SendNotificationWhenPostIsUnliked::class) ->listen(PostWasUnliked::class, Listener\SendNotificationWhenPostIsUnliked::class)
->subscribe(Listener\SaveLikesToDatabase::class), ->listen(Deleted::class, [Listener\SaveLikesToDatabase::class, 'whenPostIsDeleted'])
->listen(Saving::class, [Listener\SaveLikesToDatabase::class, 'whenPostIsSaving']),
(new Extend\Filter(PostFilterer::class)) (new Extend\Filter(PostFilterer::class))
->addFilter(LikedByFilter::class), ->addFilter(LikedByFilter::class),

View File

@@ -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,GCLRF,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,MCJ3ER,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,M,+BCLvD,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,yD","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":""}

File diff suppressed because one or more lines are too long

View File

@@ -13,23 +13,13 @@ use Flarum\Likes\Event\PostWasLiked;
use Flarum\Likes\Event\PostWasUnliked; use Flarum\Likes\Event\PostWasUnliked;
use Flarum\Post\Event\Deleted; use Flarum\Post\Event\Deleted;
use Flarum\Post\Event\Saving; use Flarum\Post\Event\Saving;
use Illuminate\Contracts\Events\Dispatcher;
class SaveLikesToDatabase class SaveLikesToDatabase
{ {
/**
* @param Dispatcher $events
*/
public function subscribe(Dispatcher $events)
{
$events->listen(Saving::class, [$this, 'whenPostIsSaving']);
$events->listen(Deleted::class, [$this, 'whenPostIsDeleted']);
}
/** /**
* @param Saving $event * @param Saving $event
*/ */
public function whenPostIsSaving(Saving $event) public static function whenPostIsSaving(Saving $event)
{ {
$post = $event->post; $post = $event->post;
$data = $event->data; $data = $event->data;
@@ -57,7 +47,7 @@ class SaveLikesToDatabase
/** /**
* @param Deleted $event * @param Deleted $event
*/ */
public function whenPostIsDeleted(Deleted $event) public static function whenPostIsDeleted(Deleted $event)
{ {
$event->post->likes()->detach(); $event->post->likes()->detach();
} }

View File

@@ -19,7 +19,7 @@
} }
], ],
"require": { "require": {
"flarum/core": "^1.6" "flarum/core": "^1.4"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

View File

@@ -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,GCLRF,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,MCJ3ER,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,M,+BCLvD,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,Q","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":""}

File diff suppressed because one or more lines are too long

View File

@@ -18,6 +18,10 @@
"build": "webpack --mode production", "build": "webpack --mode production",
"format": "prettier --write src", "format": "prettier --write src",
"format-check": "prettier --check src", "format-check": "prettier --check src",
"analyze": "cross-env ANALYZER=true yarn run build" "analyze": "cross-env ANALYZER=true yarn run build",
"clean-typings": "npx rimraf dist-typings && mkdir dist-typings",
"build-typings": "npm run clean-typings && cp -r src/@types dist-typings/@types && tsc",
"check-typings": "tsc --noEmit --emitDeclarationOnly false",
"check-typings-coverage": "typescript-coverage-report"
} }
} }

View File

@@ -19,7 +19,7 @@
} }
], ],
"require": { "require": {
"flarum/core": "^1.6" "flarum/core": "^1.4"
}, },
"extra": { "extra": {
"branch-alias": { "branch-alias": {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -19,7 +19,7 @@
} }
], ],
"require": { "require": {
"flarum/core": "^1.6" "flarum/core": "^1.4"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

View File

@@ -12,11 +12,10 @@ namespace Flarum\Mentions;
use Flarum\Api\Controller; use Flarum\Api\Controller;
use Flarum\Api\Serializer\BasicPostSerializer; use Flarum\Api\Serializer\BasicPostSerializer;
use Flarum\Api\Serializer\BasicUserSerializer; use Flarum\Api\Serializer\BasicUserSerializer;
use Flarum\Api\Serializer\CurrentUserSerializer;
use Flarum\Api\Serializer\GroupSerializer;
use Flarum\Api\Serializer\PostSerializer; use Flarum\Api\Serializer\PostSerializer;
use Flarum\Extend; use Flarum\Extend;
use Flarum\Group\Group; use Flarum\Mentions\Notification\PostMentionedBlueprint;
use Flarum\Mentions\Notification\UserMentionedBlueprint;
use Flarum\Post\Event\Deleted; use Flarum\Post\Event\Deleted;
use Flarum\Post\Event\Hidden; use Flarum\Post\Event\Hidden;
use Flarum\Post\Event\Posted; use Flarum\Post\Event\Posted;
@@ -38,16 +37,13 @@ return [
->configure(ConfigureMentions::class) ->configure(ConfigureMentions::class)
->render(Formatter\FormatPostMentions::class) ->render(Formatter\FormatPostMentions::class)
->render(Formatter\FormatUserMentions::class) ->render(Formatter\FormatUserMentions::class)
->render(Formatter\FormatGroupMentions::class)
->unparse(Formatter\UnparsePostMentions::class) ->unparse(Formatter\UnparsePostMentions::class)
->unparse(Formatter\UnparseUserMentions::class) ->unparse(Formatter\UnparseUserMentions::class),
->parse(Formatter\CheckPermissions::class),
(new Extend\Model(Post::class)) (new Extend\Model(Post::class))
->belongsToMany('mentionedBy', Post::class, 'post_mentions_post', 'mentions_post_id', 'post_id') ->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('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'), new Extend\Locales(__DIR__.'/locale'),
@@ -55,28 +51,25 @@ return [
->namespace('flarum-mentions', __DIR__.'/views'), ->namespace('flarum-mentions', __DIR__.'/views'),
(new Extend\Notification()) (new Extend\Notification())
->type(Notification\PostMentionedBlueprint::class, PostSerializer::class, ['alert']) ->type(PostMentionedBlueprint::class, PostSerializer::class, ['alert'])
->type(Notification\UserMentionedBlueprint::class, PostSerializer::class, ['alert']) ->type(UserMentionedBlueprint::class, PostSerializer::class, ['alert']),
->type(Notification\GroupMentionedBlueprint::class, PostSerializer::class, ['alert']),
(new Extend\ApiSerializer(BasicPostSerializer::class)) (new Extend\ApiSerializer(BasicPostSerializer::class))
->hasMany('mentionedBy', BasicPostSerializer::class) ->hasMany('mentionedBy', BasicPostSerializer::class)
->hasMany('mentionsPosts', BasicPostSerializer::class) ->hasMany('mentionsPosts', BasicPostSerializer::class)
->hasMany('mentionsUsers', BasicUserSerializer::class) ->hasMany('mentionsUsers', BasicUserSerializer::class),
->hasMany('mentionsGroups', GroupSerializer::class),
(new Extend\ApiController(Controller\ShowDiscussionController::class)) (new Extend\ApiController(Controller\ShowDiscussionController::class))
->addInclude(['posts.mentionedBy', 'posts.mentionedBy.user', 'posts.mentionedBy.discussion']) ->addInclude(['posts.mentionedBy', 'posts.mentionedBy.user', 'posts.mentionedBy.discussion'])
->load([ ->load([
'posts.mentionsUsers', 'posts.mentionsPosts', 'posts.mentionsPosts.user', 'posts.mentionedBy', 'posts.mentionsUsers', 'posts.mentionsPosts', 'posts.mentionsPosts.user', 'posts.mentionedBy',
'posts.mentionedBy.mentionsPosts', 'posts.mentionedBy.mentionsPosts.user', 'posts.mentionedBy.mentionsUsers', 'posts.mentionedBy.mentionsPosts', 'posts.mentionedBy.mentionsPosts.user', 'posts.mentionedBy.mentionsUsers',
'posts.mentionsGroups'
]), ]),
(new Extend\ApiController(Controller\ListDiscussionsController::class)) (new Extend\ApiController(Controller\ListDiscussionsController::class))
->load([ ->load([
'firstPost.mentionsUsers', 'firstPost.mentionsPosts', 'firstPost.mentionsPosts.user', 'firstPost.mentionsGroups', 'firstPost.mentionsUsers', 'firstPost.mentionsPosts', 'firstPost.mentionsPosts.user',
'lastPost.mentionsUsers', 'lastPost.mentionsPosts', 'lastPost.mentionsPosts.user', 'lastPost.mentionsGroups' 'lastPost.mentionsUsers', 'lastPost.mentionsPosts', 'lastPost.mentionsPosts.user'
]), ]),
(new Extend\ApiController(Controller\ShowPostController::class)) (new Extend\ApiController(Controller\ShowPostController::class))
@@ -87,16 +80,13 @@ return [
->load([ ->load([
'mentionsUsers', 'mentionsPosts', 'mentionsPosts.user', 'mentionedBy', 'mentionsUsers', 'mentionsPosts', 'mentionsPosts.user', 'mentionedBy',
'mentionedBy.mentionsPosts', 'mentionedBy.mentionsPosts.user', 'mentionedBy.mentionsUsers', 'mentionedBy.mentionsPosts', 'mentionedBy.mentionsPosts.user', 'mentionedBy.mentionsUsers',
'mentionsGroups'
]), ]),
(new Extend\ApiController(Controller\CreatePostController::class)) (new Extend\ApiController(Controller\CreatePostController::class))
->addInclude(['mentionsPosts', 'mentionsPosts.mentionedBy']) ->addInclude(['mentionsPosts', 'mentionsPosts.mentionedBy']),
->addOptionalInclude('mentionsGroups'),
(new Extend\ApiController(Controller\UpdatePostController::class)) (new Extend\ApiController(Controller\UpdatePostController::class))
->addInclude(['mentionsPosts', 'mentionsPosts.mentionedBy']) ->addInclude(['mentionsPosts', 'mentionsPosts.mentionedBy']),
->addOptionalInclude('mentionsGroups'),
(new Extend\ApiController(Controller\AbstractSerializeController::class)) (new Extend\ApiController(Controller\AbstractSerializeController::class))
->prepareDataForSerialization(FilterVisiblePosts::class), ->prepareDataForSerialization(FilterVisiblePosts::class),
@@ -113,9 +103,4 @@ return [
(new Extend\Filter(PostFilterer::class)) (new Extend\Filter(PostFilterer::class))
->addFilter(Filter\MentionedFilter::class), ->addFilter(Filter\MentionedFilter::class),
(new Extend\ApiSerializer(CurrentUserSerializer::class))
->attribute('canMentionGroups', function (CurrentUserSerializer $serializer, User $user, array $attributes): bool {
return $user->can('mentionGroups');
})
]; ];

View File

@@ -1,2 +1,2 @@
(()=>{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})(); (()=>{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})();
//# sourceMappingURL=admin.js.map //# sourceMappingURL=admin.js.map

View File

@@ -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,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,QAEL,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":""} {"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,GCLRF,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,MCJ3ER,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,M,+BCLvD,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,mE","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":""}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,20 +1,10 @@
import app from 'flarum/admin/app'; import app from 'flarum/admin/app';
app.initializers.add('flarum-mentions', function () { app.initializers.add('flarum-mentions', function () {
app.extensionData app.extensionData.for('flarum-mentions').registerSetting({
.for('flarum-mentions') setting: 'flarum-mentions.allow_username_format',
.registerSetting({ type: 'boolean',
setting: 'flarum-mentions.allow_username_format', label: app.translator.trans('flarum-mentions.admin.settings.allow_username_format_label'),
type: 'boolean', help: app.translator.trans('flarum-mentions.admin.settings.allow_username_format_text'),
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'
);
}); });

View File

@@ -10,8 +10,6 @@ import highlight from 'flarum/common/helpers/highlight';
import KeyboardNavigatable from 'flarum/forum/utils/KeyboardNavigatable'; import KeyboardNavigatable from 'flarum/forum/utils/KeyboardNavigatable';
import { truncate } from 'flarum/common/utils/string'; import { truncate } from 'flarum/common/utils/string';
import { throttle } from 'flarum/common/utils/throttleDebounce'; 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 AutocompleteDropdown from './fragments/AutocompleteDropdown';
import getMentionText from './utils/getMentionText'; import getMentionText from './utils/getMentionText';
@@ -31,7 +29,6 @@ const throttledSearch = throttle(
buildSuggestions(); buildSuggestions();
}); });
searched.push(typedLower); searched.push(typedLower);
} }
} }
@@ -69,13 +66,6 @@ export default function addComposerAutocomplete() {
const returnedUsers = Array.from(app.store.all('users')); const returnedUsers = Array.from(app.store.all('users'));
const returnedUserIds = new Set(returnedUsers.map((u) => u.id())); 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) => { const applySuggestion = (replacement) => {
this.attrs.composer.editor.replaceBeforeCursor(absMentionStart - 1, replacement + ' '); this.attrs.composer.editor.replaceBeforeCursor(absMentionStart - 1, replacement + ' ');
@@ -134,41 +124,12 @@ 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 userMatches = function (user) {
const names = [user.username(), user.displayName()]; const names = [user.username(), user.displayName()];
return names.some((name) => name.toLowerCase().substr(0, typed.length) === typed); 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 buildSuggestions = () => {
const suggestions = []; const suggestions = [];
@@ -180,15 +141,6 @@ export default function addComposerAutocomplete() {
suggestions.push(makeSuggestion(user, getMentionText(user), '', 'MentionsDropdown-user')); 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 // If the user is replying to a discussion, or if they are editing a

View File

@@ -1,4 +1,3 @@
import GroupMentionedNotification from './components/GroupMentionedNotification';
import MentionsUserPage from './components/MentionsUserPage'; import MentionsUserPage from './components/MentionsUserPage';
import PostMentionedNotification from './components/PostMentionedNotification'; import PostMentionedNotification from './components/PostMentionedNotification';
import UserMentionedNotification from './components/UserMentionedNotification'; import UserMentionedNotification from './components/UserMentionedNotification';
@@ -14,7 +13,6 @@ export default {
'mentions/components/MentionsUserPage': MentionsUserPage, 'mentions/components/MentionsUserPage': MentionsUserPage,
'mentions/components/PostMentionedNotification': PostMentionedNotification, 'mentions/components/PostMentionedNotification': PostMentionedNotification,
'mentions/components/UserMentionedNotification': UserMentionedNotification, 'mentions/components/UserMentionedNotification': UserMentionedNotification,
'mentions/components/GroupMentionedNotification': GroupMentionedNotification,
'mentions/fragments/AutocompleteDropdown': AutocompleteDropdown, 'mentions/fragments/AutocompleteDropdown': AutocompleteDropdown,
'mentions/fragments/PostQuoteButton': PostQuoteButton, 'mentions/fragments/PostQuoteButton': PostQuoteButton,
'mentions/utils/getCleanDisplayName': getCleanDisplayName, 'mentions/utils/getCleanDisplayName': getCleanDisplayName,

View File

@@ -1,25 +0,0 @@
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);
}
}

View File

@@ -10,16 +10,11 @@ import addPostQuoteButton from './addPostQuoteButton';
import addComposerAutocomplete from './addComposerAutocomplete'; import addComposerAutocomplete from './addComposerAutocomplete';
import PostMentionedNotification from './components/PostMentionedNotification'; import PostMentionedNotification from './components/PostMentionedNotification';
import UserMentionedNotification from './components/UserMentionedNotification'; import UserMentionedNotification from './components/UserMentionedNotification';
import GroupMentionedNotification from './components/GroupMentionedNotification';
import UserPage from 'flarum/forum/components/UserPage'; import UserPage from 'flarum/forum/components/UserPage';
import LinkButton from 'flarum/common/components/LinkButton'; import LinkButton from 'flarum/common/components/LinkButton';
import MentionsUserPage from './components/MentionsUserPage'; import MentionsUserPage from './components/MentionsUserPage';
import User from 'flarum/common/models/User';
import Model from 'flarum/common/Model';
app.initializers.add('flarum-mentions', function () { app.initializers.add('flarum-mentions', function () {
User.prototype.canMentionGroups = Model.attribute('canMentionGroups');
// For every mention of a post inside a post's content, set up a hover handler // For every mention of a post inside a post's content, set up a hover handler
// that shows a preview of the mentioned post. // that shows a preview of the mentioned post.
addPostMentionPreviews(); addPostMentionPreviews();
@@ -41,7 +36,6 @@ app.initializers.add('flarum-mentions', function () {
app.notificationComponents.postMentioned = PostMentionedNotification; app.notificationComponents.postMentioned = PostMentionedNotification;
app.notificationComponents.userMentioned = UserMentionedNotification; app.notificationComponents.userMentioned = UserMentionedNotification;
app.notificationComponents.groupMentioned = GroupMentionedNotification;
// Add notification preferences. // Add notification preferences.
extend(NotificationGrid.prototype, 'notificationTypes', function (items) { extend(NotificationGrid.prototype, 'notificationTypes', function (items) {
@@ -56,12 +50,6 @@ app.initializers.add('flarum-mentions', function () {
icon: 'fas fa-at', icon: 'fas fa-at',
label: app.translator.trans('flarum-mentions.forum.settings.notify_user_mentioned_label'), 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 // Add mentions tab in user profile

View File

@@ -1,7 +1,7 @@
import getCleanDisplayName, { shouldUseOldFormat } from './getCleanDisplayName'; import getCleanDisplayName, { shouldUseOldFormat } from './getCleanDisplayName';
/** /**
* Fetches the mention text for a specified user (and optionally a post ID for replies, or group). * Fetches the mention text for a specified user (and optionally a post ID for replies).
* *
* Automatically determines which mention syntax to be used based on the option in the * Automatically determines which mention syntax to be used based on the option in the
* admin dashboard. Also performs display name clean-up automatically. * admin dashboard. Also performs display name clean-up automatically.
@@ -17,13 +17,9 @@ import getCleanDisplayName, { shouldUseOldFormat } from './getCleanDisplayName';
* @example <caption>Using old syntax</caption> * @example <caption>Using old syntax</caption>
* // '@username' * // '@username'
* getMentionText(User) // User's username is '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, group) { export default function getMentionText(user, postId) {
if (user !== undefined && postId === undefined) { if (postId === undefined) {
if (shouldUseOldFormat()) { if (shouldUseOldFormat()) {
// Plain @username // Plain @username
const cleanText = getCleanDisplayName(user, false); const cleanText = getCleanDisplayName(user, false);
@@ -32,14 +28,9 @@ export default function getMentionText(user, postId, group) {
// @"Display name"#UserID // @"Display name"#UserID
const cleanText = getCleanDisplayName(user); const cleanText = getCleanDisplayName(user);
return `@"${cleanText}"#${user.id()}`; return `@"${cleanText}"#${user.id()}`;
} else if (user !== undefined && postId !== undefined) { } else {
// @"Display name"#pPostID // @"Display name"#pPostID
const cleanText = getCleanDisplayName(user); const cleanText = getCleanDisplayName(user);
return `@"${cleanText}"#p${postId}`; return `@"${cleanText}"#p${postId}`;
} else if (group !== undefined) {
// @"Name Plural"#gGroupID
return `@"${group.namePlural()}"#g${group.id()}`;
} else {
throw 'No parameters were passed';
} }
} }

View File

@@ -4,7 +4,7 @@
export default function selectedText(body) { export default function selectedText(body) {
const selection = window.getSelection(); const selection = window.getSelection();
if (!selection.isCollapsed) { if (selection?.rangeCount) {
const range = selection.getRangeAt(0); const range = selection.getRangeAt(0);
const parent = range.commonAncestorContainer; const parent = range.commonAncestorContainer;

View File

@@ -1,7 +1,6 @@
import app from 'flarum/forum/app'; import app from 'flarum/forum/app';
import username from 'flarum/common/helpers/username'; import username from 'flarum/common/helpers/username';
import extractText from 'flarum/common/utils/extractText'; import extractText from 'flarum/common/utils/extractText';
import isDark from 'flarum/common/utils/isDark';
export function filterUserMentions(tag) { export function filterUserMentions(tag) {
let user; let user;
@@ -32,20 +31,3 @@ export function filterPostMentions(tag) {
return true; 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());
tag.setAttribute('class', isDark(group.color()) ? 'GroupMention--light' : 'GroupMention--dark');
return true;
}
}
tag.invalidate();
}

View File

@@ -1,4 +1,4 @@
.PostMention, .UserMention, .GroupMention { .PostMention, .UserMention {
background: @control-bg; background: @control-bg;
color: @control-color; color: @control-color;
border-radius: @border-radius; border-radius: @border-radius;
@@ -14,7 +14,7 @@
color: @link-color; color: @link-color;
} }
} }
.UserMention, .PostMention, .GroupMention { .UserMention, .PostMention {
&--deleted { &--deleted {
opacity: 0.8; opacity: 0.8;
filter: grayscale(1); filter: grayscale(1);
@@ -97,45 +97,6 @@
position: absolute; position: absolute;
.Button--color(@tooltip-color, @tooltip-bg); .Button--color(@tooltip-color, @tooltip-bg);
} }
.GroupMention {
& when (@config-dark-mode = false) {
&,
&:hover,
&:active {
color: @text-on-light;
}
}
& when (@config-dark-mode = true) {
&,
&:hover,
&:active {
color: @text-on-dark;
}
}
&--light {
&,
&:hover,
&:active {
color: @text-on-light;
}
}
&--dark {
&,
&:hover,
&:active {
color: @text-on-dark;
}
}
.icon {
margin-left: 5px;
}
}
.MentionsDropdown .Badge {
box-shadow: none;
}
@media @phone { @media @phone {
.MentionsDropdown { .MentionsDropdown {

View File

@@ -7,9 +7,6 @@ flarum-mentions:
# Translations in this namespace are used by the admin interface. # Translations in this namespace are used by the admin interface.
admin: admin:
# These translations are used in the mentions permissions
permissions:
mention_groups_label: Mention groups
# These translations are used in the mentions Settings page. # These translations are used in the mentions Settings page.
settings: settings:
allow_username_format_label: Allow username mention format (@Username) allow_username_format_label: Allow username mention format (@Username)
@@ -22,7 +19,7 @@ flarum-mentions:
# These translations are used by the composer (reply autocompletion function). # These translations are used by the composer (reply autocompletion function).
composer: composer:
mention_tooltip: Mention a user, group or post mention_tooltip: Mention a user or post
reply_to_post_text: "Reply to #{number}" reply_to_post_text: "Reply to #{number}"
# These translations are used by the Notifications dropdown, a.k.a. "the bell". # These translations are used by the Notifications dropdown, a.k.a. "the bell".
@@ -30,7 +27,6 @@ flarum-mentions:
others_text: => core.ref.some_others others_text: => core.ref.some_others
post_mentioned_text: "{username} replied to your post" # Can be pluralized to agree with the number of users! post_mentioned_text: "{username} replied to your post" # Can be pluralized to agree with the number of users!
user_mentioned_text: "{username} mentioned you" 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. # These translations are displayed beneath individual posts.
post: post:
@@ -45,7 +41,6 @@ flarum-mentions:
settings: settings:
notify_post_mentioned_label: Someone replies to one of my posts notify_post_mentioned_label: Someone replies to one of my posts
notify_user_mentioned_label: Someone mentions me in a post 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. # These translations are used in the user profile page and profile popup.
user: user:
@@ -55,9 +50,6 @@ flarum-mentions:
post_mention: post_mention:
deleted_text: "[unknown]" deleted_text: "[unknown]"
group_mention:
deleted_text: "[unknown group]"
# Translations in this namespace are used in emails sent by the forum. # Translations in this namespace are used in emails sent by the forum.
email: email:
@@ -88,16 +80,4 @@ flarum-mentions:
--- ---
{content} {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}

View File

@@ -1,29 +0,0 @@
<?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');
}
];

View File

@@ -9,12 +9,10 @@
namespace Flarum\Mentions; namespace Flarum\Mentions;
use Flarum\Group\Group;
use Flarum\Http\UrlGenerator; use Flarum\Http\UrlGenerator;
use Flarum\Post\CommentPost; use Flarum\Post\CommentPost;
use Flarum\Settings\SettingsRepositoryInterface; use Flarum\Settings\SettingsRepositoryInterface;
use Flarum\User\User; use Flarum\User\User;
use Illuminate\Support\Str;
use s9e\TextFormatter\Configurator; use s9e\TextFormatter\Configurator;
class ConfigureMentions class ConfigureMentions
@@ -36,7 +34,6 @@ class ConfigureMentions
{ {
$this->configureUserMentions($config); $this->configureUserMentions($config);
$this->configurePostMentions($config); $this->configurePostMentions($config);
$this->configureGroupMentions($config);
} }
private function configureUserMentions(Configurator $config) private function configureUserMentions(Configurator $config)
@@ -139,80 +136,4 @@ class ConfigureMentions
return true; 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('class');
$tag->attributes->add('id')->filterChain->append('#uint');
$tag->template = '
<xsl:choose>
<xsl:when test="@deleted != 1">
<span class="GroupMention {@class}" style="background: {@color}">@<xsl:value-of select="@groupname"/><i class="icon {@icon}"></i></span>
</xsl:when>
<xsl:otherwise>
<span class="GroupMention GroupMention--deleted" style="background: {@color}">@<xsl:value-of select="@groupname"/><i class="icon {@icon}"></i></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
*/
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);
if (! empty($group->color)) {
$tag->setAttribute('class', self::isDark($group->color) ? 'GroupMention--light' : 'GroupMention--dark');
} else {
$tag->setAttribute('class', '');
}
return true;
}
$tag->invalidate();
}
/**
* The `isDark` utility converts a hex color to rgb, and then calcul a YIQ
* value in order to get the appropriate brightness value (is it dark or is it
* light?) See https://www.w3.org/TR/AERT/#color-contrast for references. A YIQ
* value >= 128 is a light color.
*/
public static function isDark(?string $hexColor): bool
{
if (! $hexColor) {
return false;
}
$hexNumbers = Str::replace('#', '', $hexColor);
if (Str::length($hexNumbers) === 3) {
$hexNumbers += $hexNumbers;
}
$r = hexdec(Str::substr($hexNumbers, 0, 2));
$g = hexdec(Str::subStr($hexNumbers, 2, 2));
$b = hexdec(Str::subStr($hexNumbers, 4, 2));
$yiq = ($r * 299 + $g * 587 + $b * 114) / 1000;
return $yiq >= 128 ? false : true;
}
} }

View File

@@ -54,8 +54,8 @@ class FilterVisiblePosts
|| $controller instanceof Controller\CreatePostController || $controller instanceof Controller\CreatePostController
|| $controller instanceof Controller\UpdatePostController) { || $controller instanceof Controller\UpdatePostController) {
$relations = [ $relations = [
'mentionsUsers', 'mentionsPosts', 'mentionsPosts.user', 'mentionedBy', 'mentionsGroups', 'mentionsUsers', 'mentionsPosts', 'mentionsPosts.user', 'mentionedBy',
'mentionedBy.mentionsPosts', 'mentionedBy.mentionsPosts.user', 'mentionedBy.mentionsUsers', 'mentionedBy.mentionsGroups.group' 'mentionedBy.mentionsPosts', 'mentionedBy.mentionsPosts.user', 'mentionedBy.mentionsUsers'
]; ];
$posts = [$data]; $posts = [$data];

View File

@@ -1,26 +0,0 @@
<?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;
}
}

View File

@@ -1,59 +0,0 @@
<?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;
});
}
}

View File

@@ -40,8 +40,5 @@ class UpdateMentionsMetadataWhenInvisible
// Remove post mentions // Remove post mentions
$event->post->mentionsPosts()->sync([]); $event->post->mentionsPosts()->sync([]);
// Remove group mentions
$event->post->mentionsGroups()->sync([]);
} }
} }

View File

@@ -9,7 +9,6 @@
namespace Flarum\Mentions\Listener; namespace Flarum\Mentions\Listener;
use Flarum\Mentions\Notification\GroupMentionedBlueprint;
use Flarum\Mentions\Notification\PostMentionedBlueprint; use Flarum\Mentions\Notification\PostMentionedBlueprint;
use Flarum\Mentions\Notification\UserMentionedBlueprint; use Flarum\Mentions\Notification\UserMentionedBlueprint;
use Flarum\Notification\NotificationSyncer; use Flarum\Notification\NotificationSyncer;
@@ -51,11 +50,6 @@ class UpdateMentionsMetadataWhenVisible
$event->post, $event->post,
Utils::getAttributeValues($content, 'POSTMENTION', 'id') Utils::getAttributeValues($content, 'POSTMENTION', 'id')
); );
$this->syncGroupMentions(
$event->post,
Utils::getAttributeValues($content, 'GROUPMENTION', 'id')
);
} }
protected function syncUserMentions(Post $post, array $mentioned) protected function syncUserMentions(Post $post, array $mentioned)
@@ -66,7 +60,7 @@ class UpdateMentionsMetadataWhenVisible
$users = User::whereIn('id', $mentioned) $users = User::whereIn('id', $mentioned)
->get() ->get()
->filter(function ($user) use ($post) { ->filter(function ($user) use ($post) {
return $post->isVisibleTo($user) && $user->id !== $post->user_id; return $post->isVisibleTo($user) && $user->id !== $post->user->id;
}) })
->all(); ->all();
@@ -81,8 +75,8 @@ class UpdateMentionsMetadataWhenVisible
$posts = Post::with('user') $posts = Post::with('user')
->whereIn('id', $mentioned) ->whereIn('id', $mentioned)
->get() ->get()
->filter(function (Post $post) use ($reply) { ->filter(function ($post) use ($reply) {
return $post->user && $post->user_id !== $reply->user_id && $reply->isVisibleTo($post->user); return $post->user && $post->user->id !== $reply->user_id && $reply->isVisibleTo($post->user);
}) })
->all(); ->all();
@@ -90,21 +84,4 @@ class UpdateMentionsMetadataWhenVisible
$this->notifications->sync(new PostMentionedBlueprint($post, $reply), [$post->user]); $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);
}
} }

View File

@@ -1,89 +0,0 @@
<?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;
}
}

View File

@@ -1,420 +0,0 @@
<?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('<p>One of the <span style="background:#80349E" class="GroupMention ">@Mods<i class="icon fas fa-bolt"></i></span> will look at this</p>', $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));
}
}

View File

@@ -47,14 +47,12 @@ class PostMentionsTest extends TestCase
['id' => 8, 'number' => 6, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 4, 'type' => 'comment', 'content' => '<r><POSTMENTION displayname="i_am_a_deleted_user" id="2020" number="8" discussionid="2" username="i_am_a_deleted_user">@"i_am_a_deleted_user"#p2020</POSTMENTION></r>'], ['id' => 8, 'number' => 6, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 4, 'type' => 'comment', 'content' => '<r><POSTMENTION displayname="i_am_a_deleted_user" id="2020" number="8" discussionid="2" username="i_am_a_deleted_user">@"i_am_a_deleted_user"#p2020</POSTMENTION></r>'],
['id' => 9, 'number' => 10, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 5, 'type' => 'comment', 'content' => '<r><p>I am bad</p></r>'], ['id' => 9, 'number' => 10, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 5, 'type' => 'comment', 'content' => '<r><p>I am bad</p></r>'],
['id' => 10, 'number' => 11, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 4, 'type' => 'comment', 'content' => '<r><POSTMENTION displayname="Bad &quot;#p6 User" id="9" number="10" discussionid="2">@"Bad "#p6 User"#p9</POSTMENTION></r>'], ['id' => 10, 'number' => 11, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 4, 'type' => 'comment', 'content' => '<r><POSTMENTION displayname="Bad &quot;#p6 User" id="9" number="10" discussionid="2">@"Bad "#p6 User"#p9</POSTMENTION></r>'],
['id' => 11, 'number' => 12, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 40, 'type' => 'comment', 'content' => '<r><POSTMENTION displayname="Bad &quot;#p6 User" id="9" number="10" discussionid="2">@"Bad "#p6 User"#p9</POSTMENTION></r>'],
['id' => 12, 'number' => 13, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 4, 'type' => 'comment', 'content' => '<r><POSTMENTION displayname="deleted_user" id="11" number="12" discussionid="2">@"acme"#p11</POSTMENTION></r>'],
], ],
'post_mentions_post' => [ 'post_mentions_post' => [
['post_id' => 4, 'mentions_post_id' => 5], ['post_id' => 4, 'mentions_post_id' => 5],
['post_id' => 5, 'mentions_post_id' => 4], ['post_id' => 5, 'mentions_post_id' => 4],
['post_id' => 6, 'mentions_post_id' => 7], ['post_id' => 6, 'mentions_post_id' => 7],
['post_id' => 10, 'mentions_post_id' => 9], ['post_id' => 10, 'mentions_post_id' => 9]
], ],
]); ]);
@@ -419,90 +417,6 @@ class PostMentionsTest extends TestCase
$this->assertStringContainsString('PostMention', $response['data']['attributes']['contentHtml']); $this->assertStringContainsString('PostMention', $response['data']['attributes']['contentHtml']);
$this->assertNotNull(CommentPost::find($response['data']['id'])->mentionsPosts->find(9)); $this->assertNotNull(CommentPost::find($response['data']['id'])->mentionsPosts->find(9));
} }
/**
* @test
*/
public function editing_a_post_that_has_a_mention_works()
{
$response = $this->send(
$this->request('PATCH', '/api/posts/10', [
'authenticatedAs' => 1,
'json' => [
'data' => [
'attributes' => [
'content' => '@"Bad _ User"#p9',
],
],
],
])
);
$this->assertEquals(200, $response->getStatusCode());
$response = json_decode($response->getBody(), true);
$this->assertStringContainsString('Bad "#p6 User', $response['data']['attributes']['contentHtml']);
$this->assertEquals('@"Bad _ User"#p9', $response['data']['attributes']['content']);
$this->assertStringContainsString('PostMention', $response['data']['attributes']['contentHtml']);
$this->assertNotNull(CommentPost::find($response['data']['id'])->mentionsPosts->find(9));
}
/**
* @test
*/
public function editing_a_post_with_deleted_author_that_has_a_mention_works()
{
$response = $this->send(
$this->request('PATCH', '/api/posts/11', [
'authenticatedAs' => 1,
'json' => [
'data' => [
'attributes' => [
'content' => '@"Bad _ User"#p9',
],
],
],
])
);
$this->assertEquals(200, $response->getStatusCode());
$response = json_decode($response->getBody(), true);
$this->assertStringContainsString('Bad "#p6 User', $response['data']['attributes']['contentHtml']);
$this->assertEquals('@"Bad _ User"#p9', $response['data']['attributes']['content']);
$this->assertStringContainsString('PostMention', $response['data']['attributes']['contentHtml']);
$this->assertNotNull(CommentPost::find($response['data']['id'])->mentionsPosts->find(9));
}
/**
* @test
*/
public function editing_a_post_with_a_mention_of_a_post_with_deleted_author_works()
{
$response = $this->send(
$this->request('PATCH', '/api/posts/12', [
'authenticatedAs' => 1,
'json' => [
'data' => [
'attributes' => [
'content' => '@"acme"#p11',
],
],
],
])
);
$this->assertEquals(200, $response->getStatusCode());
$response = json_decode($response->getBody(), true);
$this->assertStringContainsString('[deleted]', $response['data']['attributes']['contentHtml']);
$this->assertEquals('@"[deleted]"#p11', $response['data']['attributes']['content']);
$this->assertStringContainsString('PostMention', $response['data']['attributes']['contentHtml']);
$this->assertNotNull(CommentPost::find($response['data']['id'])->mentionsPosts->find(11));
}
} }
class CustomOtherDisplayNameDriver implements DriverInterface class CustomOtherDisplayNameDriver implements DriverInterface

View File

@@ -44,11 +44,10 @@ class UserMentionsTest extends TestCase
['id' => 4, 'number' => 2, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 3, 'type' => 'comment', 'content' => '<r><USERMENTION displayname="TobyFlarum___" id="4" username="toby">@tobyuuu</USERMENTION></r>'], ['id' => 4, 'number' => 2, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 3, 'type' => 'comment', 'content' => '<r><USERMENTION displayname="TobyFlarum___" id="4" username="toby">@tobyuuu</USERMENTION></r>'],
['id' => 6, 'number' => 3, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 4, 'type' => 'comment', 'content' => '<r><USERMENTION displayname="i_am_a_deleted_user" id="2021" username="i_am_a_deleted_user">@"i_am_a_deleted_user"#2021</USERMENTION></r>'], ['id' => 6, 'number' => 3, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 4, 'type' => 'comment', 'content' => '<r><USERMENTION displayname="i_am_a_deleted_user" id="2021" username="i_am_a_deleted_user">@"i_am_a_deleted_user"#2021</USERMENTION></r>'],
['id' => 10, 'number' => 11, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 5, 'type' => 'comment', 'content' => '<r><USERMENTION displayname="Bad &quot;#p6 User" id="5">@"Bad "#p6 User"#5</USERMENTION></r>'], ['id' => 10, 'number' => 11, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 5, 'type' => 'comment', 'content' => '<r><USERMENTION displayname="Bad &quot;#p6 User" id="5">@"Bad "#p6 User"#5</USERMENTION></r>'],
['id' => 11, 'number' => 12, 'discussion_id' => 2, 'created_at' => Carbon::now(), 'user_id' => 50, 'type' => 'comment', 'content' => '<r><USERMENTION displayname="Bad &quot;#p6 User" id="5">@"Bad "#p6 User"#5</USERMENTION></r>'],
], ],
'post_mentions_user' => [ 'post_mentions_user' => [
['post_id' => 4, 'mentions_user_id' => 4], ['post_id' => 4, 'mentions_user_id' => 4],
['post_id' => 10, 'mentions_user_id' => 5], ['post_id' => 10, 'mentions_user_id' => 5]
], ],
]); ]);
@@ -439,62 +438,6 @@ class UserMentionsTest extends TestCase
$this->assertStringContainsString('UserMention', $response['data']['attributes']['contentHtml']); $this->assertStringContainsString('UserMention', $response['data']['attributes']['contentHtml']);
$this->assertNotNull(CommentPost::find($response['data']['id'])->mentionsUsers->find(5)); $this->assertNotNull(CommentPost::find($response['data']['id'])->mentionsUsers->find(5));
} }
/**
* @test
*/
public function editing_a_post_that_has_a_mention_works()
{
$response = $this->send(
$this->request('PATCH', '/api/posts/10', [
'authenticatedAs' => 1,
'json' => [
'data' => [
'attributes' => [
'content' => '@"Bad _ User"#5',
],
],
],
])
);
$this->assertEquals(200, $response->getStatusCode());
$response = json_decode($response->getBody(), true);
$this->assertStringContainsString('Bad "#p6 User', $response['data']['attributes']['contentHtml']);
$this->assertEquals('@"Bad _ User"#5', $response['data']['attributes']['content']);
$this->assertStringContainsString('UserMention', $response['data']['attributes']['contentHtml']);
$this->assertNotNull(CommentPost::find($response['data']['id'])->mentionsUsers->find(5));
}
/**
* @test
*/
public function editing_a_post_with_deleted_author_that_has_a_mention_works()
{
$response = $this->send(
$this->request('PATCH', '/api/posts/11', [
'authenticatedAs' => 1,
'json' => [
'data' => [
'attributes' => [
'content' => '@"Bad _ User"#5',
],
],
],
])
);
$this->assertEquals(200, $response->getStatusCode());
$response = json_decode($response->getBody(), true);
$this->assertStringContainsString('Bad "#p6 User', $response['data']['attributes']['contentHtml']);
$this->assertEquals('@"Bad _ User"#5', $response['data']['attributes']['content']);
$this->assertStringContainsString('UserMention', $response['data']['attributes']['contentHtml']);
$this->assertNotNull(CommentPost::find($response['data']['id'])->mentionsUsers->find(5));
}
} }
class CustomDisplayNameDriver implements DriverInterface class CustomDisplayNameDriver implements DriverInterface

View File

@@ -1,7 +0,0 @@
{!! $translator->trans('flarum-mentions.email.group_mentioned.body', [
'{recipient_display_name}' => $user->display_name,
'{mentioner_display_name}' => $blueprint->post->user->display_name,
'{title}' => $blueprint->post->discussion->title,
'{url}' => $url->to('forum')->route('discussion', ['id' => $blueprint->post->discussion_id, 'near' => $blueprint->post->number]),
'{content}' => $blueprint->post->content
]) !!}

View File

@@ -19,7 +19,7 @@
} }
], ],
"require": { "require": {
"flarum/core": "^1.6" "flarum/core": "^1.4"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -22,7 +22,7 @@
"source": "https://github.com/flarum/package-manager" "source": "https://github.com/flarum/package-manager"
}, },
"require": { "require": {
"flarum/core": "^1.5.0", "flarum/core": "^1.0.0",
"composer/composer": "^2.3" "composer/composer": "^2.3"
}, },
"require-dev": { "require-dev": {

Some files were not shown because too many files have changed in this diff Show More