mirror of
https://github.com/flarum/core.git
synced 2025-08-14 04:14:06 +02:00
Compare commits
2 Commits
v1.8.9
...
im/approva
Author | SHA1 | Date | |
---|---|---|---|
|
ad47ac3266 | ||
|
121e4d3c0e |
@@ -18,8 +18,5 @@ trim_trailing_whitespace = false
|
||||
[*.{php,xml,json}]
|
||||
indent_size = 4
|
||||
|
||||
[{tsconfig.json,prettierrc.json}]
|
||||
[tsconfig.json]
|
||||
indent_size = 2
|
||||
|
||||
[*.neon]
|
||||
indent_style = tab
|
||||
|
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@@ -1 +0,0 @@
|
||||
* @flarum/core
|
126
.github/workflows/REUSABLE_backend.yml
vendored
126
.github/workflows/REUSABLE_backend.yml
vendored
@@ -9,12 +9,6 @@ on:
|
||||
default: true
|
||||
required: false
|
||||
|
||||
enable_phpstan:
|
||||
description: "Enable PHPStan Static Analysis?"
|
||||
type: boolean
|
||||
default: false
|
||||
required: false
|
||||
|
||||
backend_directory:
|
||||
description: The directory of the project where backend code is located. This should contain a `composer.json` file, and is generally the root directory of the repo.
|
||||
type: string
|
||||
@@ -25,19 +19,12 @@ on:
|
||||
description: Versions of PHP to test with. Should be array of strings encoded as JSON array
|
||||
type: string
|
||||
required: false
|
||||
default: '["7.3", "7.4", "8.0", "8.1", "8.2", "8.3"]'
|
||||
|
||||
php_extensions:
|
||||
description: PHP extensions to install.
|
||||
type: string
|
||||
required: false
|
||||
default: 'curl, dom, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip'
|
||||
|
||||
default: '["7.4", "8.0", "8.1"]'
|
||||
db_versions:
|
||||
description: Versions of databases to test with. Should be array of strings encoded as JSON array
|
||||
type: string
|
||||
required: false
|
||||
default: '["mysql:5.7", "mysql:8.0.30", "mariadb"]'
|
||||
default: '["mysql:5.7", "mariadb"]'
|
||||
|
||||
php_ini_values:
|
||||
description: PHP ini values
|
||||
@@ -45,82 +32,35 @@ on:
|
||||
required: false
|
||||
default: error_reporting=E_ALL
|
||||
|
||||
runner_type:
|
||||
description: The type of runner to use for the jobs. This should be one of the types supported by the `runs-on` keyword.
|
||||
type: string
|
||||
required: false
|
||||
default: 'ubuntu-latest'
|
||||
|
||||
secrets:
|
||||
composer_auth:
|
||||
description: The Composer auth tokens to use for private packages.
|
||||
required: false
|
||||
|
||||
env:
|
||||
COMPOSER_ROOT_VERSION: dev-main
|
||||
FLARUM_TEST_TMP_DIR_LOCAL: tests/integration/tmp
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ${{ inputs.runner_type }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php: ${{ fromJSON(inputs.php_versions) }}
|
||||
service: ${{ fromJSON(inputs.db_versions) }}
|
||||
prefix: ['']
|
||||
php_ini_values: [inputs.php_ini_values]
|
||||
prefix: ['', flarum_]
|
||||
|
||||
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixinclude
|
||||
include:
|
||||
# Expands the matrix by naming DBs.
|
||||
- service: 'mysql:5.7'
|
||||
db: MySQL 5.7
|
||||
- service: 'mysql:8.0.30'
|
||||
db: MySQL 8.0
|
||||
db: MySQL
|
||||
- service: mariadb
|
||||
db: MariaDB
|
||||
|
||||
# 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_
|
||||
- prefix: flarum_
|
||||
prefixStr: (prefix)
|
||||
|
||||
# @TODO: remove in 2.0
|
||||
# Include testing PHP 8.2 with deprecation warnings disabled.
|
||||
- php: 8.2
|
||||
php_ini_values: error_reporting=E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED
|
||||
- php: 8.3
|
||||
php_ini_values: error_reporting=E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED
|
||||
# - php: 8.4
|
||||
# php_ini_values: error_reporting=E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED
|
||||
|
||||
# To reduce number of actions, we exclude some PHP versions from running with some DB versions.
|
||||
exclude:
|
||||
- php: ${{ fromJSON(inputs.php_versions)[1] }}
|
||||
service: 'mysql:8.0.30'
|
||||
- php: ${{ fromJSON(inputs.php_versions)[2] }}
|
||||
service: 'mysql:8.0.30'
|
||||
- php: ${{ fromJSON(inputs.php_versions)[3] }}
|
||||
service: 'mysql:8.0.30'
|
||||
|
||||
# @TODO: remove in 2.0
|
||||
# Exclude testing PHP 8.2 with deprecation warnings enabled.
|
||||
- php: 8.2
|
||||
php_ini_values: error_reporting=E_ALL
|
||||
- php: 8.0
|
||||
service: 'mysql:5.7'
|
||||
prefix: flarum_
|
||||
- php: 8.0
|
||||
service: mariadb
|
||||
prefix: flarum_
|
||||
|
||||
services:
|
||||
mysql:
|
||||
@@ -130,9 +70,7 @@ jobs:
|
||||
|
||||
name: 'PHP ${{ matrix.php }} / ${{ matrix.db }} ${{ matrix.prefixStr }}'
|
||||
|
||||
if: >-
|
||||
inputs.enable_backend_testing &&
|
||||
((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || github.event_name != 'pull_request')
|
||||
if: inputs.enable_backend_testing
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
@@ -142,9 +80,9 @@ jobs:
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
coverage: xdebug
|
||||
extensions: ${{ inputs.php_extensions }}
|
||||
extensions: curl, dom, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip
|
||||
tools: phpunit, composer:v2
|
||||
ini-values: ${{ matrix.php_ini_values }}
|
||||
ini-values: ${{ inputs.php_ini_values }}
|
||||
|
||||
# The authentication alter is necessary because newer mysql versions use the `caching_sha2_password` driver,
|
||||
# which isn't supported prior to PHP7.4
|
||||
@@ -172,37 +110,3 @@ jobs:
|
||||
working-directory: ${{ inputs.backend_directory }}
|
||||
env:
|
||||
COMPOSER_PROCESS_TIMEOUT: 600
|
||||
|
||||
phpstan:
|
||||
runs-on: ${{ inputs.runner_type }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php: ${{ fromJSON(inputs.php_versions) }}
|
||||
# exclude:
|
||||
# - php: 8.4
|
||||
|
||||
name: 'PHPStan PHP ${{ matrix.php }}'
|
||||
|
||||
if: >-
|
||||
inputs.enable_phpstan &&
|
||||
((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || github.event_name != 'pull_request')
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
coverage: xdebug
|
||||
extensions: ${{ inputs.php_extensions }}
|
||||
tools: phpunit, composer:v2
|
||||
ini-values: ${{ matrix.php_ini_values }}
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer install
|
||||
working-directory: ${{ inputs.backend_directory }}
|
||||
|
||||
- name: Run PHPStan
|
||||
run: composer analyse:phpstan
|
||||
|
37
.github/workflows/REUSABLE_frontend.yml
vendored
37
.github/workflows/REUSABLE_frontend.yml
vendored
@@ -28,11 +28,6 @@ on:
|
||||
type: string
|
||||
required: false
|
||||
default: check-typings-coverage
|
||||
test_script:
|
||||
description: "Script to run for tests. Empty value to disable."
|
||||
type: string
|
||||
required: false
|
||||
default: test
|
||||
|
||||
enable_bundlewatch:
|
||||
description: "Enable Bundlewatch?"
|
||||
@@ -49,11 +44,6 @@ on:
|
||||
type: boolean
|
||||
default: true
|
||||
required: false
|
||||
enable_tests:
|
||||
description: "Enable Tests?"
|
||||
type: boolean
|
||||
default: false
|
||||
required: false
|
||||
|
||||
backend_directory:
|
||||
description: The directory of the project where backend code is located. This should contain a `composer.json` file, and is generally the root directory of the repo.
|
||||
@@ -74,7 +64,7 @@ on:
|
||||
description: The node version to use for the workflow.
|
||||
type: number
|
||||
required: false
|
||||
default: 20
|
||||
default: 16
|
||||
|
||||
js_package_manager:
|
||||
description: "Enable TypeScript?"
|
||||
@@ -86,41 +76,27 @@ on:
|
||||
type: string
|
||||
required: false
|
||||
|
||||
runner_type:
|
||||
description: The type of runner to use for the jobs. This should be one of the types supported by the `runs-on` keyword.
|
||||
type: string
|
||||
required: false
|
||||
default: 'ubuntu-latest'
|
||||
|
||||
secrets:
|
||||
bundlewatch_github_token:
|
||||
description: The GitHub token to use for Bundlewatch.
|
||||
required: false
|
||||
composer_auth:
|
||||
description: The Composer auth tokens to use for private packages.
|
||||
required: false
|
||||
|
||||
env:
|
||||
COMPOSER_ROOT_VERSION: dev-main
|
||||
ci_script: ${{ inputs.js_package_manager == 'yarn' && 'yarn install --immutable' || 'npm ci' }}
|
||||
cache_dependency_path: ${{ inputs.cache_dependency_path || format(inputs.js_package_manager == 'yarn' && '{0}/yarn.lock' || '{0}/package-lock.json', inputs.frontend_directory) }}
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
DISABLE_V8_COMPILE_CACHE: 1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Checks & Build
|
||||
runs-on: ${{ inputs.runner_type }}
|
||||
|
||||
if: >-
|
||||
((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || github.event_name != 'pull_request')
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ inputs.node_version }}
|
||||
cache: ${{ inputs.js_package_manager }}
|
||||
@@ -129,7 +105,7 @@ jobs:
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.2'
|
||||
php-version: '8.0'
|
||||
extensions: curl, dom, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip
|
||||
tools: composer:v2
|
||||
|
||||
@@ -143,7 +119,7 @@ jobs:
|
||||
working-directory: ${{ inputs.frontend_directory }}
|
||||
|
||||
- name: JS Checks & Production Build
|
||||
uses: flarum/action-build@v4
|
||||
uses: flarum/action-build@3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
build_script: ${{ inputs.build_script }}
|
||||
@@ -151,7 +127,6 @@ jobs:
|
||||
format_script: ${{ inputs.enable_prettier == true && inputs.format_script || '' }}
|
||||
check_typings_script: ${{ inputs.enable_typescript == true && inputs.check_typings_script || '' }}
|
||||
type_coverage_script: ${{ inputs.enable_typescript == true && inputs.type_coverage_script || '' }}
|
||||
test_script: ${{ inputs.enable_tests == true && inputs.test_script || '' }}
|
||||
package_manager: ${{ inputs.js_package_manager }}
|
||||
js_path: ${{ inputs.frontend_directory }}
|
||||
do_not_commit: ${{ github.ref != format('refs/heads/{0}', inputs.main_git_branch) || github.event_name != 'push' }}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
name: Extension Manager PHP
|
||||
name: Package Manager PHP
|
||||
|
||||
on: [workflow_dispatch, push, pull_request]
|
||||
|
||||
@@ -6,6 +6,6 @@ jobs:
|
||||
run:
|
||||
uses: ./.github/workflows/REUSABLE_backend.yml
|
||||
with:
|
||||
enable_backend_testing: false
|
||||
enable_backend_testing: true
|
||||
|
||||
backend_directory: ./extensions/package-manager
|
5
.github/workflows/frontend.yml
vendored
5
.github/workflows/frontend.yml
vendored
@@ -10,10 +10,7 @@ jobs:
|
||||
backend_directory: ./
|
||||
js_package_manager: yarn
|
||||
cache_dependency_path: ./yarn.lock
|
||||
main_git_branch: 1.x
|
||||
enable_tests: true
|
||||
# @TODO: fix bundlewatch
|
||||
enable_bundlewatch: false
|
||||
main_git_branch: main
|
||||
|
||||
secrets:
|
||||
bundlewatch_github_token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}
|
||||
|
12
.github/workflows/phpstan.yml
vendored
12
.github/workflows/phpstan.yml
vendored
@@ -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: .
|
8
.github/workflows/prepare-release.yml
vendored
8
.github/workflows/prepare-release.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
- name: Prepare release
|
||||
uses: flarum/action-release@master
|
||||
with:
|
||||
next_tag: ${{ inputs.version }}
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
open_collective_token: ${{ secrets.OPEN_COLLECTIVE_TOKEN }}
|
||||
env:
|
||||
NEXT_TAG: ${{ inputs.version }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
OPEN_COLLECTIVE_TOKEN: ${{ secrets.OPEN_COLLECTIVE_TOKEN }}
|
||||
|
320
CHANGELOG.md
320
CHANGELOG.md
@@ -1,325 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## [v1.8.9](https://github.com/flarum/framework/compare/v1.8.8...v1.8.9)
|
||||
### Fixed
|
||||
* change condition when unread label is shown in Scrubber (https://github.com/flarum/framework/pull/4116)
|
||||
* resolve a11y warnings in Admin Frontend (https://github.com/flarum/framework/pull/4114)
|
||||
* return empty object if selected mail driver is unavailable (https://github.com/flarum/framework/pull/4113)
|
||||
### Changed
|
||||
* change private to protected, allowing extensibility (https://github.com/flarum/framework/pull/4119)
|
||||
* change length of email field (https://github.com/flarum/framework/pull/4117)
|
||||
### Added
|
||||
* Implement Support for Translatable Validation Attribute Errors (https://github.com/flarum/framework/pull/4070)
|
||||
* PHP 8.4 support (https://github.com/flarum/framework/pull/4105)
|
||||
* conditional extend whenExtensionDisabled (https://github.com/flarum/framework/pull/4107)
|
||||
|
||||
## [v1.8.8](https://github.com/flarum/framework/compare/v1.8.7...v1.8.8)
|
||||
### Fixed
|
||||
* previously suspended admin users cannot remove their avatar after suspension (https://github.com/flarum/framework/pull/4071)
|
||||
* new search term not being passed (https://github.com/flarum/framework/pull/4083)
|
||||
* postfooter did not apply the empty subclass (https://github.com/flarum/framework/pull/4085)
|
||||
|
||||
## [v1.8.7](https://github.com/flarum/framework/compare/v1.8.6...v1.8.7)
|
||||
### Fixed
|
||||
* BasicsPage not viewable if only one language pack enabled, and/or `flarum/nicknames` not enabled (https://github.com/flarum/framework/pull/4062)
|
||||
|
||||
## [v1.8.6](https://github.com/flarum/framework/compare/v1.8.5...v1.8.6)
|
||||
### Fixed
|
||||
* reset admin page save button in catch handler (https://github.com/flarum/framework/pull/3963)
|
||||
* suspended users can remove avatar (https://github.com/flarum/framework/pull/3998)
|
||||
* return null if content left empty in formatter (https://github.com/flarum/framework/pull/4059)
|
||||
### Changed
|
||||
* allow DiscussionsSearchSource to be extended (https://github.com/flarum/framework/pull/4025)
|
||||
* allow modifying the discussion title on PostsUserPage (https://github.com/flarum/framework/pull/4031)
|
||||
* make it easier to modify AppearancePage, BasicsPage, MailPage (https://github.com/flarum/framework/pull/4037)
|
||||
* point fontawesome links at v5 free (https://github.com/flarum/framework/pull/4038)
|
||||
* make WelcomeHero extensible (https://github.com/flarum/framework/pull/4039)
|
||||
* make PostMeta extensible (https://github.com/flarum/framework/pull/4040)
|
||||
* extensible TagHero (https://github.com/flarum/framework/pull/4041)
|
||||
* allow extending PostPreview content (https://github.com/flarum/framework/pull/4043)
|
||||
* allow classes that extends AbstractJob to be placed on a specified queue (https://github.com/flarum/framework/pull/4026)
|
||||
* use common component for ip address display (https://github.com/flarum/framework/pull/4042)
|
||||
* make it easier to add content after the first post (https://github.com/flarum/framework/pull/4050)
|
||||
* improve extensibility of IndexPage (https://github.com/flarum/framework/pull/4045)
|
||||
* improve extensibility of DiscussionPage (https://github.com/flarum/framework/pull/4046)
|
||||
* backport & improve extensibility of DiscussionListItem (https://github.com/flarum/framework/pull/4048)
|
||||
* improve & use extensibility of CommentPost & Post (https://github.com/flarum/framework/pull/4047)
|
||||
* allow labels of PostStreamScrubber to be customized (https://github.com/flarum/framework/pull/4049)
|
||||
* allow to customize time formats through translations (https://github.com/flarum/framework/pull/4053)
|
||||
### Added
|
||||
* Export all missing modules in compat (https://github.com/flarum/framework/pull/4044)
|
||||
* Add (some) missing shims (https://github.com/flarum/framework/pull/4027)
|
||||
* provide an 'actions' dropdown for extensions to add their additional buttons to the admin UserListPage (https://github.com/flarum/framework/pull/4054)
|
||||
|
||||
## [v1.8.5](https://github.com/flarum/framework/compare/v1.8.4...v1.8.5)
|
||||
### Fixed
|
||||
* Logout controller allows open redirects [#3948]
|
||||
|
||||
## [v1.8.4](https://github.com/flarum/framework/compare/v1.8.3...v1.8.4)
|
||||
### Fixed
|
||||
* `s9e/textformatter` 2.15 has breaking changes [#3946]
|
||||
|
||||
## [v1.8.3](https://github.com/flarum/framework/compare/v1.8.2...v1.8.3)
|
||||
### Fixed
|
||||
* Console extender does not accept ::class [#3900]
|
||||
* Conditional extender instantiation [#3898]
|
||||
|
||||
## [v1.8.2](https://github.com/flarum/framework/compare/v1.8.1...v1.8.2)
|
||||
### Fixed
|
||||
* suspended users can abuse avatar upload [#3890]
|
||||
* missing compat exports [#3888]
|
||||
|
||||
## [v1.8.1](https://github.com/flarum/framework/compare/v1.8.0...v1.8.1)
|
||||
### Fixed
|
||||
* recover temporary solution for html entities in browser title (e72541e35de4f71f9d870bbd9bb46ddf586bdf1d)
|
||||
* custom contrast color affected by parents (577890d89c593ae5b6cb96083fab69e2f1ae600c)
|
||||
* reply placeholder wrong positioning (253a3d281dbf5ce3fa712b629b80587cf67e7dbe)
|
||||
* (mentions) missed post mentions UI changes with lazy loading [#3832]
|
||||
* (mentions) cannot use newly introduced mentionables extender [#3849]
|
||||
* (mentions) missing slug from post mention links ([5a4bb7c](5a4bb7ccf226f66dd44816cb69b3d7cfe4ad7f7c))
|
||||
|
||||
## [v1.8.0](https://github.com/flarum/framework/compare/v1.7.1...v1.8.0)
|
||||
### Fixed
|
||||
- (a11y) reply placeholder not accessible [#3793]
|
||||
- (bbcode) highlight.js does not work after changing post content [#3817]
|
||||
- (bbcode) localize quote `wrote` string [#3809]
|
||||
- (mentions) mentions XHR fired even after mentioning is done [#3806]
|
||||
- (package-manager) available core updates cause an error in the dashboard ([fab71f2](fab71f2d01fa20ce9b3002833339dc5ea3ea6301))
|
||||
- (tags) not all tags are loaded in the permission grid [#3804]
|
||||
- (tags) tag discussion modal filters with exact matches only after first index [#3786]
|
||||
- (testing) always clear cache in integration test's tearDown [#3818]
|
||||
- `UserSecurityPage` not exported ([232618a](232618aba604ab003425df38b895208c863d3260))
|
||||
- `isDark()` utility can receive null value [#3774]
|
||||
- approving a post does not bump user `comment_count` [#3790]
|
||||
- circular dependencies disable all involved extensions [#3785]
|
||||
- color input overflowing the input box [#3796]
|
||||
- deleting a discussion from the profile does not visually remove it [#3799]
|
||||
- discussion page showing horizontal scroll on iOS [#3821]
|
||||
- empty string displayed as SelectDropdown title [#3773]
|
||||
- filter values are not validated [#3795]
|
||||
- infinite scroll not initialized for notifications on big screens [#3733]
|
||||
- notification subject discussion eager loading fails [#3788]
|
||||
- null as 2nd param in `preg_match` is deprecated [#3801]
|
||||
- unread count in post stream not visible [#3791]
|
||||
- unreadable badge icon on certain colors [#3810]
|
||||
- integrity constraint violation [#3772]
|
||||
### Changed
|
||||
- (core,mentions) limit `mentionedBy` post relation results [#3780]
|
||||
- (likes) limit `likes` relationship results [#3781]
|
||||
- Change some methods from private to protected, to be able to extend the affected classes [#3802]
|
||||
- Do not catch exceptions when testing Console commands [#3813]
|
||||
- drop usage of jquery in `install` and `update` interfaces [#3797]
|
||||
- extensibility improvements [#3729]
|
||||
- major frontend JS cleanup [#3609]
|
||||
- revert ineffective code for encoding of page title [#3768]
|
||||
- speed up post creation time [#3808]
|
||||
### Added
|
||||
- (mentions,tags) tag mentions [#3769]
|
||||
- add delete own posts permission [#3784]
|
||||
- add a trait to flush the formatter cache in tests [#3811]
|
||||
- add user creation to users list page [#3744]
|
||||
- cli command for enabling or disabling an extension [#3816]
|
||||
- conditional extenders [#3759]
|
||||
- provide old content to `Revised` event [#3789]
|
||||
|
||||
## [v1.7.1](https://github.com/flarum/framework/compare/v1.7.0...v1.7.1)
|
||||
### Fixed
|
||||
- (tags) composer tag selection modal using wrong primary max & min numbers (abc9670659426b765274376945b818b70d84848c)
|
||||
- missing parameter names in token title translation. (#3752)
|
||||
- hardcoded language strings in StatusWidget (#3754)
|
||||
- hide developer tokens section in if there is nothing to display or create (#3753)
|
||||
- improve sessions user UI on mobile (dd868ab44e11e892d020e3b9412553c6a789e68d)
|
||||
|
||||
## [v1.7.0](https://github.com/flarum/framework/compare/v1.6.3...v1.7.0)
|
||||
### Added
|
||||
- (actions) allow running JS tests in GH actions [#3730]
|
||||
- (core) PHP 8.2 Support [#3709]
|
||||
- (jest) create jest config package for unit testing [#3678]
|
||||
- (jest) mithril component testing [#3679]
|
||||
- (phpstan) foundation for usage in extensions [#3666]
|
||||
- (seo) Do not use h3 header for poster author in posts stream [#3732]
|
||||
- (seo) Use h2 header for discussions on discussions list [#3731]
|
||||
- (seo) shift h1 tag from logo to discussion title [#3724]
|
||||
- (tags) admin tag selection component (reusable tag selection modal) [#3686]
|
||||
- Admin User Search [#3712]
|
||||
- access tokens user management UI [#3587]
|
||||
- add display name column to admin users list [#3740]
|
||||
- allow push additional items to the end of the poststream [#3691]
|
||||
- allow using utf8 characters in tag slugs [#3588]
|
||||
- expose queue driver, schedule status [#3593]
|
||||
- expose {time} to eventPost data, fix renamed tooltip [#3698]
|
||||
- frontend `Model` extender [#3646]
|
||||
- global logout to clear all sessions, access tokens, email tokens and password tokens [#3605]
|
||||
- improved page navigation for users list [#3741]
|
||||
- introduce frontend extenders [#3645]
|
||||
### Fixed
|
||||
- (mentions) correctly convert a 3 char. hex color to a 6 char. one [#3694]
|
||||
- (mentions) post reply mention missing notification on approval [#3738]
|
||||
- (phpstan) adapt phpstan package for extension use [#3727]
|
||||
- (tags) clickable tag labels have underline [#3737]
|
||||
- (tags) tag text color contrast [#3653]
|
||||
- 3 digit hex color value in color input not supported [#3706]
|
||||
- column `id` can be ambiguous in group filter with extensions [#3696]
|
||||
- disallow certain dangerous LESS features ([1761660](1761660c98ea5a3e9665fb8e6041d1f2ee62a444))
|
||||
- evaluated page title content [#3684]
|
||||
- invalid translation key for scheduler dashboard [#3736]
|
||||
- load actor.groups on showforumcontroller [#3716]
|
||||
- make go-to-page input number-like [#3743]
|
||||
- normal logout affects all sessions [#3571]
|
||||
- permissions table on mobile is unusable [#3722]
|
||||
- post dropdown opens all dropdowns in `.Post-actions` [#3675]
|
||||
- typo in Formatter extender docblock [#3676]
|
||||
- undefined showing in dropdown active title [#3700]
|
||||
### Changed
|
||||
- (phpstan) enable phpstan in bundled extensions [#3667]
|
||||
- Add missing states exports to `compat.ts` [#3683]
|
||||
- Indicate cross-origin request in generic error message [#3669]
|
||||
- Merge branch 'release/v1.6.2' ([e0b9dcf](e0b9dcfbcd7db175368dbc98255f9223da8df17d))
|
||||
- The negate field doesn't get used, which means you cant exclude tags [#3713]
|
||||
- Update forum.less to fix the misalignment of the choose tags button [#3726]
|
||||
- `yarn audit-fix` ([8ddb0fe](8ddb0feb097dad06c5763107d7a7f7b5a55562c4))
|
||||
- `yarn` ([ee1e04c](ee1e04cdc26b3e63057a58899f32f482901a95fd))
|
||||
- convert `Dropdown` components to TS [#3608]
|
||||
- fix php 8.1 on preg_match 2nd argument being null, which also optimizes slightly ([d7b9a03](d7b9a03f31847c39631ba495df8f515509774610))
|
||||
- improve group mentions parsing [#3723]
|
||||
- prepare `@flarum/jest-config` for release ([748cca6](748cca6d12f8b1744a6017c09395725bdbb4a118))
|
||||
- remove use of deprecated phpunit assertion ([3af0481](3af0481f304277f5380fac9c9b169a7fa651f53b))
|
||||
- set flarum version to 1.7.0 for dev ([2517bc0](2517bc0f70b0f0e3d3ea3f6ae06af8604d89b25d))
|
||||
- update JS dependencies [#3695]
|
||||
|
||||
## [v1.6.3](https://github.com/flarum/framework/compare/v1.6.2...v1.6.3)
|
||||
### Fixed
|
||||
* Post mentions can be used to read any post on the forum without access control (ab1c868b978e8b0d09a5d682c54665dae17d0985).
|
||||
* Notifications can leak restricted content (d0a2b95dca57d3dae9a0d77b610b1cb1d0b1766a).
|
||||
* Any user including unactivated can reply in public discussions whose first post was permanently deleted (12f14112a0ecd1484d97330b82beb2a145919015).
|
||||
* (subscriptions) Post notifications not getting access checked (https://github.com/flarum/framework/commit/e5f05166a062a9a6eb7c12e28728bfd5db7270e3).
|
||||
|
||||
## [v1.6.2](https://github.com/flarum/framework/compare/v1.6.1...v1.6.2)
|
||||
### Fixed
|
||||
* XSS Vulnerability in core (https://github.com/flarum/framework/pull/3684).
|
||||
|
||||
## [v1.6.1](https://github.com/flarum/framework/compare/v1.6.0...v1.6.1)
|
||||
### Fixed
|
||||
* JS dependencies update breaks utilities.
|
||||
|
||||
## [v1.6.0](https://github.com/flarum/framework/compare/v1.5.0...v1.6.0)
|
||||
### Fixed
|
||||
- (approval) posts approved for deleted users error ([b5874a0](b5874a08e482196f50af50aa78e43c93c29fb647))
|
||||
- (regression) bad import ([5f2d7fb](5f2d7fb7b6e430d40cf2bb05eca7c73f6ca5a2cc))
|
||||
- akismet fails when the extension is not on a version ([45d9121](45d91212f6bfa777cae9fc06c55c85d01ffd174d))
|
||||
- apply flex for AppearancePage colors input [#3651]
|
||||
- groupmentions have poor contrast on some backgrounds [#3672]
|
||||
- larastan v1 incompatible with phpstan v1.9.0 [#3665]
|
||||
- package manager failures not showing alerts [#3647]
|
||||
- password reset leaks user existence [#3616]
|
||||
- statistics previous period chart is unclear [#3654]
|
||||
### Changed
|
||||
- (package-manager) config composer to use web php version ([fd19645](fd196454a5641776784fa80886cc7577c840f8ed))
|
||||
- (package-manager) set min core version and add warning ([31c3cfc](31c3cfc4eab4c314260b9b0d11e53ac2d4be158d))
|
||||
- (statistics) prepare v1.5.1 ([dc215ab](dc215aba59145dfd7b0d6efad4388444f30e47fb))
|
||||
- Apply fixes from StyleCI ([267f675](267f6759f80bd06f468337245ea6045635e827d9))
|
||||
- Fix tag discussion count decreased by 2 when hiding before deleting [#3660]
|
||||
- Log migration path when up/down keys are missing [#3664]
|
||||
- Make it possible to extend SetupScript [#3643]
|
||||
- Setup PHPStan Level 5 [#3553]
|
||||
- `yarn format` ([c5c312d](c5c312db0d800e3b84b94a4abb9691e348dea742))
|
||||
- add missing last period to custom date ranges [#3661]
|
||||
- add priorities to profile settings page [#3657]
|
||||
- allow specifying php extensions in workflow ([b0b47a0](b0b47a0888f513a459b67e9f89e72a61de38f1ce))
|
||||
- format js ([06963df](06963df4079373fc8fc51b7479e9576f02beb098))
|
||||
- group mentions [#3658]
|
||||
- remove styleci from changelog ([b2fa28e](b2fa28e4b57094e46dbdb3d79fab74f290a17d17))
|
||||
- set flarum version to dev for 1.6.0 ([fc743ba](fc743ba88872031db13597d7365a063b8004c78f))
|
||||
- throw an exception when no serializer is provided to the controller [#3614]
|
||||
### Added
|
||||
- (statistics) support for custom date ranges [#3622]
|
||||
- Allow additional login params, Introduce `LogInValidator` [#3670]
|
||||
- Allow additional reset password params, introduce `ForgotPasswordValidator` [#3671]
|
||||
- add statistics chart export button [#3662]
|
||||
- allow specifying extensions when installing an instance [#3655]
|
||||
- contrast util with yiq calculator [#3652]
|
||||
- customizable session driver [#3610]
|
||||
- replace `ColorPreviewInput` for GroupModal color input [#3650]
|
||||
- send notifications of a new reply when post is approved [#3656]
|
||||
|
||||
## [v1.5.0](https://github.com/flarum/framework/compare/v1.4.0...v1.5.0)
|
||||
### Fixed
|
||||
- (a11y) add accessible labels to notification grid options [#3520]
|
||||
- (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)
|
||||
|
||||
### Added
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<a href="https://flarum.org/"><img src="https://flarum.org/images/flarum.svg"></a>
|
||||
<a href="https://flarum.org/"><img src="https://flarum.org/assets/img/logo.png"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
@@ -7,6 +7,7 @@
|
||||
<a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/packagist/dt/flarum/core" alt="Total Downloads"></a>
|
||||
<a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/github/v/release/flarum/core?sort=semver" alt="Latest Version"></a>
|
||||
<a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/packagist/l/flarum/core" alt="License"></a>
|
||||
<a href="https://huntr.dev/bounties/disclose/?target=https://github.com/flarum/core"><img src="https://cdn.huntr.dev/huntr_security_badge_mono.svg" alt="huntr"></a>
|
||||
<a href="https://github.styleci.io/repos/28257573"><img src="https://github.styleci.io/repos/28257573/shield?style=flat" alt="StyleCI"></a>
|
||||
</p>
|
||||
|
||||
@@ -37,4 +38,3 @@ If you discover a security vulnerability within Flarum, please send an e-mail to
|
||||
## License
|
||||
|
||||
Flarum is open-source software licensed under the [MIT License](https://github.com/flarum/flarum/blob/master/LICENSE).
|
||||
|
||||
|
@@ -40,13 +40,12 @@
|
||||
"Flarum\\": "framework/core/src",
|
||||
"Flarum\\Akismet\\": "extensions/akismet/src",
|
||||
"Flarum\\Approval\\": "extensions/approval/src",
|
||||
"Flarum\\BBCode\\": "extensions/bbcode/src",
|
||||
"Flarum\\Flags\\": "extensions/flags/src",
|
||||
"Flarum\\Likes\\": "extensions/likes/src",
|
||||
"Flarum\\Lock\\": "extensions/lock/src",
|
||||
"Flarum\\Mentions\\": "extensions/mentions/src",
|
||||
"Flarum\\Nicknames\\": "extensions/nicknames/src",
|
||||
"Flarum\\ExtensionManager\\": "extensions/package-manager/src",
|
||||
"Flarum\\PackageManager\\": "extensions/package-manager/src",
|
||||
"Flarum\\Pusher\\": "extensions/pusher/src",
|
||||
"Flarum\\Statistics\\": "extensions/statistics/src",
|
||||
"Flarum\\Sticky\\": "extensions/sticky/src",
|
||||
@@ -74,7 +73,7 @@
|
||||
"flarum/markdown": "self.version",
|
||||
"flarum/mentions": "self.version",
|
||||
"flarum/nicknames": "self.version",
|
||||
"flarum/extension-manager": "self.version",
|
||||
"flarum/package-manager": "self.version",
|
||||
"flarum/pusher": "self.version",
|
||||
"flarum/statistics": "self.version",
|
||||
"flarum/sticky": "self.version",
|
||||
@@ -85,8 +84,8 @@
|
||||
"flarum/testing": "self.version"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.3",
|
||||
"ext-json": "*",
|
||||
"php": ">=7.3",
|
||||
"components/font-awesome": "^5.14.0",
|
||||
"composer/composer": "^2.0",
|
||||
"dflydev/fig-cookies": "^3.0.0",
|
||||
@@ -111,10 +110,9 @@
|
||||
"illuminate/validation": "^8.0",
|
||||
"illuminate/view": "^8.0",
|
||||
"intervention/image": "2.5.* || ^2.6.1",
|
||||
"jenssegers/agent": "^2.6",
|
||||
"laminas/laminas-diactoros": "^2.4.1 || ^3.0.0",
|
||||
"laminas/laminas-httphandlerrunner": "^1.2.0 || ^2.3.0 || ^3.0.0",
|
||||
"laminas/laminas-stratigility": "^3.2.2 || ^4.0.0",
|
||||
"laminas/laminas-diactoros": "^2.4.1",
|
||||
"laminas/laminas-httphandlerrunner": "^1.2.0",
|
||||
"laminas/laminas-stratigility": "^3.2.2",
|
||||
"league/flysystem": "^1.0.11",
|
||||
"matthiasmullie/minify": "^1.3",
|
||||
"middlewares/base-path": "^2.0.1",
|
||||
@@ -127,8 +125,7 @@
|
||||
"psr/http-server-handler": "^1.0",
|
||||
"psr/http-server-middleware": "^1.0",
|
||||
"pusher/pusher-php-server": "^2.2",
|
||||
"s9e/text-formatter": ">=2.3.6 <2.15",
|
||||
"staudenmeir/eloquent-eager-limit": "^1.0",
|
||||
"s9e/text-formatter": "^2.3.6",
|
||||
"sycho/json-api": "^0.5.0",
|
||||
"sycho/sourcemap": "^2.0.0",
|
||||
"symfony/config": "^5.2.2",
|
||||
@@ -143,8 +140,8 @@
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.4",
|
||||
"phpunit/phpunit": "^9.0",
|
||||
"phpstan/phpstan": ">=1.8.11 < 1.9.0",
|
||||
"nunomaduro/larastan": "^1.0"
|
||||
"phpstan/phpstan-php-parser": "^1.0",
|
||||
"phpstan/phpstan": "^1.2"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
@@ -181,12 +178,5 @@
|
||||
"extension.neon"
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"analyse:phpstan": "phpstan analyse",
|
||||
"clear-cache:phpstan": "phpstan clear-result-cache"
|
||||
},
|
||||
"scripts-descriptions": {
|
||||
"analyse:phpstan": "Run static analysis"
|
||||
}
|
||||
}
|
||||
|
@@ -19,8 +19,8 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.8",
|
||||
"flarum/approval": "^1.7"
|
||||
"flarum/core": "^1.4",
|
||||
"flarum/approval": "^1.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@@ -13,7 +13,6 @@ use Flarum\Approval\Event\PostWasApproved;
|
||||
use Flarum\Extend;
|
||||
use Flarum\Post\Event\Hidden;
|
||||
use Flarum\Post\Event\Saving;
|
||||
use Flarum\Post\Post;
|
||||
|
||||
return [
|
||||
(new Extend\Frontend('forum'))
|
||||
@@ -31,7 +30,4 @@ return [
|
||||
|
||||
(new Extend\ServiceProvider())
|
||||
->register(AkismetProvider::class),
|
||||
|
||||
(new Extend\Model(Post::class))
|
||||
->cast('is_spam', 'bool'),
|
||||
];
|
||||
|
2
extensions/akismet/js/dist/admin.js.map
generated
vendored
2
extensions/akismet/js/dist/admin.js.map
generated
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,IACzBH,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,kBAAkB,WACrCA,IAAAA,cAAAA,IACO,kBACJC,gBAAgB,CACfC,QAAS,yBACTC,KAAM,OACNC,MAAOJ,IAAAA,WAAAA,MAAqB,yDAE7BC,gBAAgB,CAEfC,QAAS,qCACTC,KAAM,UACNC,MAAOJ,IAAAA,WAAAA,MAAqB,mEAC5BK,KAAML,IAAAA,WAAAA,MAAqB,oEAE5BM,mBACC,CACEC,KAAM,kBACNH,MAAOJ,IAAAA,WAAAA,MAAqB,mDAC5BQ,WAAY,iBAEd,QAEN,G","sources":["webpack://@flarum/akismet/webpack/bootstrap","webpack://@flarum/akismet/webpack/runtime/compat get default export","webpack://@flarum/akismet/webpack/runtime/define property getters","webpack://@flarum/akismet/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/akismet/webpack/runtime/make namespace object","webpack://@flarum/akismet/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/akismet/./src/admin/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-akismet', () => {\n app.extensionData\n .for('flarum-akismet')\n .registerSetting({\n setting: 'flarum-akismet.api_key',\n type: 'text',\n label: app.translator.trans('flarum-akismet.admin.akismet_settings.api_key_label'),\n })\n .registerSetting({\n //https://blog.akismet.com/2014/04/23/theres-a-ninja-in-your-akismet/\n setting: 'flarum-akismet.delete_blatant_spam',\n type: 'boolean',\n label: app.translator.trans('flarum-akismet.admin.akismet_settings.delete_blatant_spam_label'),\n help: app.translator.trans('flarum-akismet.admin.akismet_settings.delete_blatant_spam_help'),\n })\n .registerPermission(\n {\n icon: 'fas fa-vote-yea',\n label: app.translator.trans('flarum-akismet.admin.permissions.bypass_akismet'),\n permission: 'bypassAkismet',\n },\n 'start'\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerSetting","setting","type","label","help","registerPermission","icon","permission"],"sourceRoot":""}
|
||||
{"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":""}
|
2
extensions/akismet/js/dist/forum.js
generated
vendored
2
extensions/akismet/js/dist/forum.js
generated
vendored
@@ -1,2 +1,2 @@
|
||||
(()=>{var t={n:e=>{var o=e&&e.__esModule?()=>e.default:()=>e;return t.d(o,{a:o}),o},d:(e,o)=>{for(var r in o)t.o(o,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:o[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};(()=>{"use strict";t.r(e);const o=flarum.core.compat["common/extend"],r=flarum.core.compat["forum/app"];var a=t.n(r);const n=flarum.core.compat["forum/utils/PostControls"];var s=t.n(n);const l=flarum.core.compat["forum/components/Post"];var u=t.n(l);a().initializers.add("flarum-akismet",(function(){(0,o.extend)(s(),"destructiveControls",(function(t,e){if(t.has("approve")){var o=e.flags();if(o&&o.some((function(t){return"akismet"===(null==t?void 0:t.type())}))){var r=t.get("approve");r&&"object"==typeof r&&"children"in r&&(r.children=a().translator.trans("flarum-akismet.forum.post.not_spam_button"))}}})),(0,o.override)(u().prototype,"flagReason",(function(t,e){return"akismet"===e.type()?a().translator.trans("flarum-akismet.forum.post.akismet_flagged_text"):t(e)}))}))})(),module.exports=e})();
|
||||
(()=>{var t={n:e=>{var o=e&&e.__esModule?()=>e.default:()=>e;return t.d(o,{a:o}),o},d:(e,o)=>{for(var r in o)t.o(o,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:o[r]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};(()=>{"use strict";t.r(e);const o=flarum.core.compat["common/extend"],r=flarum.core.compat["forum/app"];var a=t.n(r);const n=flarum.core.compat["forum/utils/PostControls"];var m=t.n(n);const s=flarum.core.compat["forum/components/CommentPost"];var l=t.n(s);a().initializers.add("flarum-akismet",(function(){(0,o.extend)(m(),"destructiveControls",(function(t,e){if(t.has("approve")){var o=e.flags();if(o&&o.some((function(t){return"akismet"===(null==t?void 0:t.type())}))){var r=t.get("approve");r&&"object"==typeof r&&"children"in r&&(r.children=a().translator.trans("flarum-akismet.forum.post.not_spam_button"))}}})),(0,o.override)(l().prototype,"flagReason",(function(t,e){return"akismet"===e.type()?a().translator.trans("flarum-akismet.forum.post.akismet_flagged_text"):t(e)}))}))})(),module.exports=e})();
|
||||
//# sourceMappingURL=forum.js.map
|
2
extensions/akismet/js/dist/forum.js.map
generated
vendored
2
extensions/akismet/js/dist/forum.js.map
generated
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"forum.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,iBCAlD,EAA+BF,OAAOC,KAAKC,OAAO,a,aCAxD,MAAM,EAA+BF,OAAOC,KAAKC,OAAO,4B,aCAxD,MAAM,EAA+BF,OAAOC,KAAKC,OAAO,yB,aCSxDC,IAAAA,aAAAA,IAAqB,kBAAkB,YACrCC,EAAAA,EAAAA,QAAOC,IAAc,uBAAuB,SAAUC,EAAmCC,GACvF,GAAID,EAAME,IAAI,WAAY,CACxB,IAAMC,EAAQF,EAAKE,QAEnB,GAAIA,GAASA,EAAMC,MAAK,SAACC,GAAI,MAAsB,aAAb,MAAJA,OAAI,EAAJA,EAAMC,OAAoB,IAAG,CAC7D,IAAMC,EAAcP,EAAMf,IAAI,WAC1BsB,GAAsC,iBAAhBA,GAA4B,aAAcA,IAClEA,EAAYC,SAAWX,IAAAA,WAAAA,MAAqB,6CAEhD,CACF,CACF,KAEAY,EAAAA,EAAAA,UAASC,IAAAA,UAAyB,cAAc,SAAUC,EAAUN,GAClE,MAAoB,YAAhBA,EAAKC,OACAT,IAAAA,WAAAA,MAAqB,kDAGvBc,EAASN,EAClB,GACF,G","sources":["webpack://@flarum/akismet/webpack/bootstrap","webpack://@flarum/akismet/webpack/runtime/compat get default export","webpack://@flarum/akismet/webpack/runtime/define property getters","webpack://@flarum/akismet/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/akismet/webpack/runtime/make namespace object","webpack://@flarum/akismet/external root \"flarum.core.compat['common/extend']\"","webpack://@flarum/akismet/external root \"flarum.core.compat['forum/app']\"","webpack://@flarum/akismet/external root \"flarum.core.compat['forum/utils/PostControls']\"","webpack://@flarum/akismet/external root \"flarum.core.compat['forum/components/Post']\"","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/Post'];","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 PostComponent from 'flarum/forum/components/Post';\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(PostComponent.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","PostComponent","original"],"sourceRoot":""}
|
||||
{"version":3,"file":"forum.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,iBCAlD,EAA+BF,OAAOC,KAAKC,OAAO,a,aCAxD,MAAM,EAA+BF,OAAOC,KAAKC,OAAO,4B,aCAxD,MAAM,EAA+BF,OAAOC,KAAKC,OAAO,gC,aCSxDC,IAAAA,aAAAA,IAAqB,kBAAkB,YACrCC,EAAAA,EAAAA,QAAOC,IAAc,uBAAuB,SAAUC,EAAmCC,GACvF,GAAID,EAAME,IAAI,WAAY,CACxB,IAAMC,EAAQF,EAAKE,QAEnB,GAAIA,GAASA,EAAMC,MAAK,SAACC,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":""}
|
@@ -20,7 +20,7 @@
|
||||
"flarum-tsconfig": "^1.0.2",
|
||||
"prettier": "^2.5.1",
|
||||
"flarum-webpack-config": "^2.0.0",
|
||||
"webpack": "^5.76.0",
|
||||
"webpack": "^5.65.0",
|
||||
"webpack-cli": "^4.9.1",
|
||||
"typescript": "^4.5.4",
|
||||
"typescript-coverage-report": "^0.6.1"
|
||||
|
@@ -4,7 +4,7 @@ import type Post from 'flarum/common/models/Post';
|
||||
import type ItemList from 'flarum/common/utils/ItemList';
|
||||
|
||||
import PostControls from 'flarum/forum/utils/PostControls';
|
||||
import PostComponent from 'flarum/forum/components/Post';
|
||||
import CommentPost from 'flarum/forum/components/CommentPost';
|
||||
import type Mithril from 'mithril';
|
||||
|
||||
app.initializers.add('flarum-akismet', () => {
|
||||
@@ -21,7 +21,7 @@ app.initializers.add('flarum-akismet', () => {
|
||||
}
|
||||
});
|
||||
|
||||
override(PostComponent.prototype, 'flagReason', function (original, flag) {
|
||||
override(CommentPost.prototype, 'flagReason', function (original, flag) {
|
||||
if (flag.type() === 'akismet') {
|
||||
return app.translator.trans('flarum-akismet.forum.post.akismet_flagged_text');
|
||||
}
|
||||
|
@@ -15,7 +15,6 @@
|
||||
"declarationDir": "./dist-typings",
|
||||
"paths": {
|
||||
"flarum/*": ["../../../framework/core/js/dist-typings/*"],
|
||||
"@flarum/core/*": ["../../../framework/core/js/dist-typings/*"],
|
||||
"flarum/flags/*": ["../../flags/js/dist-typings/*"]
|
||||
}
|
||||
}
|
||||
|
@@ -50,7 +50,7 @@ class Akismet
|
||||
$client = new Client();
|
||||
|
||||
return $client->request('POST', "$this->apiUrl/$type", [
|
||||
'headers' => [
|
||||
'headers' => [
|
||||
'User-Agent' => "Flarum/$this->flarumVersion | Akismet/$this->extensionVersion",
|
||||
],
|
||||
'form_params' => $this->params,
|
||||
|
@@ -50,7 +50,7 @@ class ValidatePost
|
||||
->withContent($post->content)
|
||||
->withAuthorName($post->user->username)
|
||||
->withAuthorEmail($post->user->email)
|
||||
->withType($post->number === 1 ? 'forum-post' : 'reply')
|
||||
->withType($post->number == 1 ? 'forum-post' : 'reply')
|
||||
->withIp($post->ip_address)
|
||||
->withUserAgent($_SERVER['HTTP_USER_AGENT'])
|
||||
->checkSpam();
|
||||
|
@@ -38,7 +38,7 @@ class AkismetProvider extends AbstractServiceProvider
|
||||
$settings->get('flarum-akismet.api_key'),
|
||||
$url->to('forum')->base(),
|
||||
$app::VERSION,
|
||||
$extensions->getExtension('flarum-akismet')->getVersion() ?? 'unknown',
|
||||
$extensions->getExtension('flarum-akismet')->getVersion(),
|
||||
$config->inDebugMode()
|
||||
);
|
||||
});
|
||||
|
@@ -19,8 +19,8 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.8",
|
||||
"flarum/flags": "^1.7"
|
||||
"flarum/core": "^1.4",
|
||||
"flarum/flags": "^1.2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@@ -10,7 +10,6 @@
|
||||
use Flarum\Api\Serializer\BasicDiscussionSerializer;
|
||||
use Flarum\Api\Serializer\PostSerializer;
|
||||
use Flarum\Approval\Access;
|
||||
use Flarum\Approval\Event\PostWasApproved;
|
||||
use Flarum\Approval\Listener;
|
||||
use Flarum\Discussion\Discussion;
|
||||
use Flarum\Extend;
|
||||
@@ -28,17 +27,15 @@ return [
|
||||
|
||||
// Discussions should be approved by default
|
||||
(new Extend\Model(Discussion::class))
|
||||
->default('is_approved', true)
|
||||
->cast('is_approved', 'bool'),
|
||||
->default('is_approved', true),
|
||||
|
||||
// Posts should be approved by default
|
||||
(new Extend\Model(Post::class))
|
||||
->default('is_approved', true)
|
||||
->cast('is_approved', 'bool'),
|
||||
->default('is_approved', true),
|
||||
|
||||
(new Extend\ApiSerializer(BasicDiscussionSerializer::class))
|
||||
->attribute('isApproved', function ($serializer, Discussion $discussion) {
|
||||
return $discussion->is_approved;
|
||||
return (bool) $discussion->is_approved;
|
||||
}),
|
||||
|
||||
(new Extend\ApiSerializer(PostSerializer::class))
|
||||
@@ -51,7 +48,6 @@ return [
|
||||
new Extend\Locales(__DIR__.'/locale'),
|
||||
|
||||
(new Extend\Event())
|
||||
->listen(PostWasApproved::class, Listener\UpdateDiscussionAfterPostApproval::class)
|
||||
->subscribe(Listener\ApproveContent::class)
|
||||
->subscribe(Listener\UnapproveNewContent::class),
|
||||
|
||||
|
2
extensions/approval/js/dist/admin.js.map
generated
vendored
2
extensions/approval/js/dist/admin.js.map
generated
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,iBCAlD,EAA+BF,OAAOC,KAAKC,OAAO,a,aCGxDC,IAAAA,aAAAA,IAAqB,mBAAmB,YACtCC,EAAAA,EAAAA,QAAOD,IAAK,0BAA0B,SAAUE,EAAUC,GACrC,oCAAfA,GACFD,EAASE,KAAK,mBAEG,oCAAfD,GACFD,EAASE,KAAK,mBAElB,IAEAJ,IAAAA,cAAAA,IACO,mBACJK,mBACC,CACEC,KAAM,eACNC,MAAOP,IAAAA,WAAAA,MAAqB,8EAC5BG,WAAY,mCAEd,QACA,IAEDE,mBACC,CACEC,KAAM,eACNC,MAAOP,IAAAA,WAAAA,MAAqB,kEAC5BG,WAAY,mCAEd,QACA,IAEDE,mBACC,CACEC,KAAM,eACNC,MAAOP,IAAAA,WAAAA,MAAqB,yDAC5BG,WAAY,2BAEd,WACA,GAEN,G","sources":["webpack://@flarum/approval/webpack/bootstrap","webpack://@flarum/approval/webpack/runtime/compat get default export","webpack://@flarum/approval/webpack/runtime/define property getters","webpack://@flarum/approval/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/approval/webpack/runtime/make namespace object","webpack://@flarum/approval/external root \"flarum.core.compat['common/extend']\"","webpack://@flarum/approval/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/approval/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['common/extend'];","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import { extend } from 'flarum/common/extend';\nimport app from 'flarum/admin/app';\n\napp.initializers.add('flarum-approval', () => {\n extend(app, 'getRequiredPermissions', function (required, permission) {\n if (permission === 'discussion.startWithoutApproval') {\n required.push('startDiscussion');\n }\n if (permission === 'discussion.replyWithoutApproval') {\n required.push('discussion.reply');\n }\n });\n\n app.extensionData\n .for('flarum-approval')\n .registerPermission(\n {\n icon: 'fas fa-check',\n label: app.translator.trans('flarum-approval.admin.permissions.start_discussions_without_approval_label'),\n permission: 'discussion.startWithoutApproval',\n },\n 'start',\n 95\n )\n .registerPermission(\n {\n icon: 'fas fa-check',\n label: app.translator.trans('flarum-approval.admin.permissions.reply_without_approval_label'),\n permission: 'discussion.replyWithoutApproval',\n },\n 'reply',\n 95\n )\n .registerPermission(\n {\n icon: 'fas fa-check',\n label: app.translator.trans('flarum-approval.admin.permissions.approve_posts_label'),\n permission: 'discussion.approvePosts',\n },\n 'moderate',\n 65\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","extend","required","permission","push","registerPermission","icon","label"],"sourceRoot":""}
|
||||
{"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":""}
|
2
extensions/approval/js/dist/forum.js.map
generated
vendored
2
extensions/approval/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
|
||||
"devDependencies": {
|
||||
"prettier": "^2.5.1",
|
||||
"flarum-webpack-config": "^2.0.0",
|
||||
"webpack": "^5.76.0",
|
||||
"webpack": "^5.65.0",
|
||||
"webpack-cli": "^4.9.1",
|
||||
"@flarum/prettier-config": "^1.0.0"
|
||||
},
|
||||
|
15
extensions/approval/js/src/@types/shims.d.ts
vendored
15
extensions/approval/js/src/@types/shims.d.ts
vendored
@@ -1,15 +0,0 @@
|
||||
import 'flarum/common/models/Discussion';
|
||||
import 'flarum/common/models/Post';
|
||||
|
||||
declare module 'flarum/common/models/Discussion' {
|
||||
export default interface Discussion {
|
||||
isApproved(): boolean;
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'flarum/common/models/Post' {
|
||||
export default interface Post {
|
||||
isApproved(): boolean;
|
||||
canApprove(): boolean;
|
||||
}
|
||||
}
|
@@ -11,7 +11,6 @@ namespace Flarum\Approval\Listener;
|
||||
|
||||
use Flarum\Approval\Event\PostWasApproved;
|
||||
use Flarum\Post\Event\Saving;
|
||||
use Flarum\User\Exception\PermissionDeniedException;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
class ApproveContent
|
||||
@@ -22,44 +21,55 @@ class ApproveContent
|
||||
public function subscribe(Dispatcher $events)
|
||||
{
|
||||
$events->listen(Saving::class, [$this, 'approvePost']);
|
||||
$events->listen(PostWasApproved::class, [$this, 'approveDiscussion']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws PermissionDeniedException
|
||||
* @param Saving $event
|
||||
*/
|
||||
public function approvePost(Saving $event)
|
||||
{
|
||||
$attributes = $event->data['attributes'];
|
||||
$post = $event->post;
|
||||
|
||||
// Nothing to do if it is already approved.
|
||||
if ($post->is_approved) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We approve a post in one of two cases:
|
||||
* - The post was unapproved and the allowed action is approving it. We trigger an event.
|
||||
* - The post was unapproved and the allowed actor is hiding or un-hiding it.
|
||||
* We approve it silently if the action is unhiding.
|
||||
*/
|
||||
$approvingSilently = false;
|
||||
|
||||
if (isset($attributes['isApproved'])) {
|
||||
$event->actor->assertCan('approve', $post);
|
||||
|
||||
$isApproved = (bool) $attributes['isApproved'];
|
||||
} elseif (isset($attributes['isHidden']) && $event->actor->can('approve', $post)) {
|
||||
} elseif (! empty($attributes['isHidden']) && $event->actor->can('approve', $post)) {
|
||||
$isApproved = true;
|
||||
$approvingSilently = $attributes['isHidden'];
|
||||
}
|
||||
|
||||
if (! empty($isApproved)) {
|
||||
$post->is_approved = true;
|
||||
|
||||
if (! $approvingSilently) {
|
||||
$post->raise(new PostWasApproved($post, $event->actor));
|
||||
}
|
||||
$post->raise(new PostWasApproved($post, $event->actor));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostWasApproved $event
|
||||
*/
|
||||
public function approveDiscussion(PostWasApproved $event)
|
||||
{
|
||||
$post = $event->post;
|
||||
$discussion = $post->discussion;
|
||||
$user = $discussion->user;
|
||||
|
||||
$discussion->refreshCommentCount();
|
||||
$discussion->refreshLastPost();
|
||||
|
||||
if ($post->number == 1) {
|
||||
$discussion->is_approved = true;
|
||||
|
||||
$discussion->afterSave(function () use ($user) {
|
||||
$user->refreshDiscussionCount();
|
||||
});
|
||||
}
|
||||
|
||||
$discussion->save();
|
||||
|
||||
$user->refreshCommentCount();
|
||||
$user->save();
|
||||
}
|
||||
}
|
||||
|
@@ -9,7 +9,6 @@
|
||||
|
||||
namespace Flarum\Approval\Listener;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Flarum\Discussion\Discussion;
|
||||
use Flarum\Flags\Flag;
|
||||
use Flarum\Post\CommentPost;
|
||||
@@ -56,7 +55,7 @@ class UnapproveNewContent
|
||||
|
||||
$flag->post_id = $post->id;
|
||||
$flag->type = 'approval';
|
||||
$flag->created_at = Carbon::now();
|
||||
$flag->created_at = time();
|
||||
|
||||
$flag->save();
|
||||
});
|
||||
|
@@ -1,45 +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();
|
||||
}
|
||||
|
||||
if ($post->user) {
|
||||
$post->user->refreshCommentCount();
|
||||
$post->user->save();
|
||||
}
|
||||
}
|
||||
}
|
@@ -28,8 +28,11 @@ trait InteractsWithUnapprovedContent
|
||||
['id' => 3, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 3, 'comment_count' => 1, 'is_approved' => 0, 'is_private' => 1],
|
||||
['id' => 4, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 4, 'comment_count' => 1, 'is_approved' => 1, 'is_private' => 0],
|
||||
['id' => 5, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 5, 'comment_count' => 1, 'is_approved' => 1, 'is_private' => 0],
|
||||
['id' => 6, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 6, 'comment_count' => 1, 'is_approved' => 0, 'is_private' => 1],
|
||||
['id' => 6, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 2, 'first_post_id' => 6, 'comment_count' => 1, 'is_approved' => 0, 'is_private' => 1],
|
||||
['id' => 7, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 7, 'comment_count' => 1, 'is_approved' => 1, 'is_private' => 0],
|
||||
|
||||
// Normal discussion with first post being private (also means comment_count = 0).
|
||||
['id' => 8, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 12, 'comment_count' => 0, 'is_approved' => 1, 'is_private' => 0],
|
||||
],
|
||||
'posts' => [
|
||||
['id' => 1, 'discussion_id' => 1, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 0, 'is_approved' => 1, 'number' => 1],
|
||||
@@ -37,39 +40,26 @@ trait InteractsWithUnapprovedContent
|
||||
['id' => 3, 'discussion_id' => 3, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 0, 'is_approved' => 1, 'number' => 1],
|
||||
['id' => 4, 'discussion_id' => 4, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 0, 'is_approved' => 1, 'number' => 1],
|
||||
['id' => 5, 'discussion_id' => 5, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 0, 'is_approved' => 1, 'number' => 1],
|
||||
['id' => 6, 'discussion_id' => 6, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 0, 'is_approved' => 1, 'number' => 1],
|
||||
['id' => 6, 'discussion_id' => 6, 'user_id' => 2, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 0, 'is_approved' => 1, 'number' => 1],
|
||||
['id' => 7, 'discussion_id' => 7, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 0, 'is_approved' => 1, 'number' => 1],
|
||||
|
||||
['id' => 8, 'discussion_id' => 7, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 0, 'is_approved' => 1, 'number' => 2],
|
||||
['id' => 9, 'discussion_id' => 7, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 1, 'is_approved' => 0, 'number' => 3],
|
||||
['id' => 9, 'discussion_id' => 7, 'user_id' => 2, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 1, 'is_approved' => 0, 'number' => 3],
|
||||
['id' => 10, 'discussion_id' => 7, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 0, 'is_approved' => 1, 'number' => 4],
|
||||
['id' => 11, 'discussion_id' => 7, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 1, 'is_approved' => 0, 'number' => 5],
|
||||
|
||||
// First post of a normal discussion being private.
|
||||
['id' => 12, 'discussion_id' => 8, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 1, 'is_approved' => 0, 'number' => 1],
|
||||
],
|
||||
'groups' => [
|
||||
['id' => 4, 'name_singular' => 'Acme', 'name_plural' => 'Acme', 'is_hidden' => 0]
|
||||
['id' => 100, 'name_singular' => 'Acme', 'name_plural' => 'Acme', 'is_hidden' => 0]
|
||||
],
|
||||
'group_user' => [
|
||||
['user_id' => 3, 'group_id' => 4]
|
||||
['user_id' => 3, 'group_id' => 100]
|
||||
],
|
||||
'group_permission' => [
|
||||
['permission' => 'discussion.approvePosts', 'group_id' => 4]
|
||||
['permission' => 'discussion.approvePosts', 'group_id' => 100]
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* null: Guest, 2: Normal User.
|
||||
*/
|
||||
public function unallowedUsers(): array
|
||||
{
|
||||
return [[null], [2]];
|
||||
}
|
||||
|
||||
/**
|
||||
* 1: Admin, 3: Permission Given, 4: Discussions Author.
|
||||
*/
|
||||
public function allowedUsers(): array
|
||||
{
|
||||
return [[1], [3], [4]];
|
||||
}
|
||||
}
|
||||
|
@@ -29,10 +29,10 @@ class ListDiscussionsTest extends TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider unallowedUsers
|
||||
* @dataProvider userVisibleDiscussionsDataProvider
|
||||
* @test
|
||||
*/
|
||||
public function can_only_see_approved_if_not_allowed_to_approve(?int $authenticatedAs)
|
||||
public function can_only_see_approved_if_allowed(?int $authenticatedAs, array $visibleDiscussionIds)
|
||||
{
|
||||
$response = $this->send(
|
||||
$this->request('GET', '/api/discussions', compact('authenticatedAs'))
|
||||
@@ -41,22 +41,17 @@ class ListDiscussionsTest extends TestCase
|
||||
$body = json_decode($response->getBody()->getContents(), true);
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertEqualsCanonicalizing([1, 4, 5, 7], Arr::pluck($body['data'], 'id'));
|
||||
$this->assertEqualsCanonicalizing($visibleDiscussionIds, Arr::pluck($body['data'], 'id'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider allowedUsers
|
||||
* @test
|
||||
*/
|
||||
public function can_see_unapproved_if_allowed_to_approve(int $authenticatedAs)
|
||||
public function userVisibleDiscussionsDataProvider(): array
|
||||
{
|
||||
$response = $this->send(
|
||||
$this->request('GET', '/api/discussions', compact('authenticatedAs'))
|
||||
);
|
||||
|
||||
$body = json_decode($response->getBody()->getContents(), true);
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertEqualsCanonicalizing([1, 2, 3, 4, 5, 6, 7], Arr::pluck($body['data'], 'id'));
|
||||
return [
|
||||
'admin can view unapproved discussions' => [1, [1, 2, 3, 4, 5, 6, 7, 8]],
|
||||
'user with perms can view unapproved discussions' => [3, [1, 2, 3, 4, 5, 6, 7, 8]],
|
||||
'guests cannot view unapproved discussions' => [null, [1, 4, 5, 7]],
|
||||
'normal users cannot view unapproved discussions unless being an author 1' => [2, [1, 4, 5, 6, 7]],
|
||||
'normal users cannot view unapproved discussions unless being an author 2' => [4, [1, 2, 3, 4, 5, 7, 8]],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -29,10 +29,10 @@ class ListPostsTest extends TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider unallowedUsers
|
||||
* @dataProvider userVisiblePostsDataProvider
|
||||
* @test
|
||||
*/
|
||||
public function can_only_see_approved_if_not_allowed_to_approve(?int $authenticatedAs)
|
||||
public function can_only_see_approved_if_allowed(?int $authenticatedAs, array $visiblePostIds)
|
||||
{
|
||||
$response = $this->send(
|
||||
$this
|
||||
@@ -47,28 +47,22 @@ class ListPostsTest extends TestCase
|
||||
$body = json_decode($response->getBody()->getContents(), true);
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertEqualsCanonicalizing([7, 8, 10], Arr::pluck($body['data'], 'id'));
|
||||
$this->assertEqualsCanonicalizing($visiblePostIds, Arr::pluck($body['data'], 'id'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider allowedUsers
|
||||
* @test
|
||||
*/
|
||||
public function can_see_unapproved_if_allowed_to_approve(int $authenticatedAs)
|
||||
public function userVisiblePostsDataProvider(): array
|
||||
{
|
||||
$response = $this->send(
|
||||
$this
|
||||
->request('GET', '/api/posts', compact('authenticatedAs'))
|
||||
->withQueryParams([
|
||||
'filter' => [
|
||||
'discussion' => 7
|
||||
]
|
||||
])
|
||||
);
|
||||
return [
|
||||
// Admin can view unapproved posts.
|
||||
[1, [7, 8, 9, 10, 11, 12]],
|
||||
|
||||
$body = json_decode($response->getBody()->getContents(), true);
|
||||
// User with approval perms can view unapproved posts.
|
||||
[3, [7, 8, 9, 10, 11, 12]],
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
$this->assertEqualsCanonicalizing([7, 8, 9, 10, 11], Arr::pluck($body['data'], 'id'));
|
||||
// Normal users cannot view unapproved posts unless being an author.
|
||||
[null, [7, 8, 10]],
|
||||
[2, [7, 8, 9, 10]],
|
||||
[4, [7, 8, 10, 11, 12]],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@@ -19,12 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Flarum\\BBCode\\": "src"
|
||||
}
|
||||
"flarum/core": "^1.4"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
|
@@ -7,14 +7,24 @@
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\BBCode;
|
||||
|
||||
use Flarum\Extend;
|
||||
use s9e\TextFormatter\Configurator;
|
||||
|
||||
return [
|
||||
new Extend\Locales(__DIR__.'/locale'),
|
||||
|
||||
(new Extend\Formatter)
|
||||
->render(Render::class)
|
||||
->configure(Configure::class),
|
||||
];
|
||||
return (new Extend\Formatter)
|
||||
->configure(function (Configurator $config) {
|
||||
$config->BBCodes->addFromRepository('B');
|
||||
$config->BBCodes->addFromRepository('I');
|
||||
$config->BBCodes->addFromRepository('U');
|
||||
$config->BBCodes->addFromRepository('S');
|
||||
$config->BBCodes->addFromRepository('URL');
|
||||
$config->BBCodes->addFromRepository('IMG');
|
||||
$config->BBCodes->addFromRepository('EMAIL');
|
||||
$config->BBCodes->addFromRepository('CODE');
|
||||
$config->BBCodes->addFromRepository('QUOTE');
|
||||
$config->BBCodes->addFromRepository('LIST');
|
||||
$config->BBCodes->addFromRepository('DEL');
|
||||
$config->BBCodes->addFromRepository('COLOR');
|
||||
$config->BBCodes->addFromRepository('CENTER');
|
||||
$config->BBCodes->addFromRepository('SIZE');
|
||||
$config->BBCodes->addFromRepository('*');
|
||||
});
|
||||
|
@@ -1,10 +0,0 @@
|
||||
flarum-bbcode:
|
||||
|
||||
##
|
||||
# UNIQUE KEYS - The following keys are used in only one location each.
|
||||
##
|
||||
|
||||
# Translations in this namespace are used by the forum user interface.
|
||||
forum:
|
||||
quote:
|
||||
wrote: wrote
|
@@ -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\BBCode;
|
||||
|
||||
use s9e\TextFormatter\Configurator;
|
||||
|
||||
class Configure
|
||||
{
|
||||
public function __invoke(Configurator $config)
|
||||
{
|
||||
$this->addTagsFromRepositories($config);
|
||||
$this->adaptHighlightJs($config);
|
||||
}
|
||||
|
||||
protected function addTagsFromRepositories(Configurator $config): void
|
||||
{
|
||||
$config->BBCodes->addFromRepository('B');
|
||||
$config->BBCodes->addFromRepository('I');
|
||||
$config->BBCodes->addFromRepository('U');
|
||||
$config->BBCodes->addFromRepository('S');
|
||||
$config->BBCodes->addFromRepository('URL');
|
||||
$config->BBCodes->addFromRepository('IMG');
|
||||
$config->BBCodes->addFromRepository('EMAIL');
|
||||
$config->BBCodes->addFromRepository('CODE');
|
||||
$config->BBCodes->addFromRepository('QUOTE', 'default', [
|
||||
'authorStr' => '<xsl:value-of select="@author"/> <xsl:value-of select="$L_WROTE"/>'
|
||||
]);
|
||||
$config->BBCodes->addFromRepository('LIST');
|
||||
$config->BBCodes->addFromRepository('DEL');
|
||||
$config->BBCodes->addFromRepository('COLOR');
|
||||
$config->BBCodes->addFromRepository('CENTER');
|
||||
$config->BBCodes->addFromRepository('SIZE');
|
||||
$config->BBCodes->addFromRepository('*');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix for highlight JS not working after changing post content.
|
||||
*
|
||||
* @link https://github.com/flarum/framework/issues/3794
|
||||
*/
|
||||
protected function adaptHighlightJs(Configurator $config): void
|
||||
{
|
||||
$codeTag = $config->tags->get('CODE');
|
||||
$script = '
|
||||
<script>
|
||||
if(window.hljsLoader && !document.currentScript.parentNode.hasAttribute(\'data-s9e-livepreview-onupdate\')) {
|
||||
window.hljsLoader.highlightBlocks(document.currentScript.parentNode);
|
||||
}
|
||||
</script>';
|
||||
$codeTag->template = str_replace('</pre>', $script.'</pre>', $codeTag->template);
|
||||
}
|
||||
}
|
@@ -1,33 +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\BBCode;
|
||||
|
||||
use s9e\TextFormatter\Renderer;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class Render
|
||||
{
|
||||
/**
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function __invoke(Renderer $renderer, $context, string $xml): string
|
||||
{
|
||||
$renderer->setParameter('L_WROTE', $this->translator->trans('flarum-bbcode.forum.quote.wrote'));
|
||||
|
||||
return $xml;
|
||||
}
|
||||
}
|
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.8"
|
||||
"flarum/core": "^1.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
2
extensions/embed/js/dist/forum.js.map
generated
vendored
2
extensions/embed/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -9,7 +9,7 @@
|
||||
"devDependencies": {
|
||||
"prettier": "^2.5.1",
|
||||
"flarum-webpack-config": "^2.0.0",
|
||||
"webpack": "^5.76.0",
|
||||
"webpack": "^5.65.0",
|
||||
"webpack-cli": "^4.9.1",
|
||||
"@flarum/prettier-config": "^1.0.0"
|
||||
},
|
||||
|
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.8"
|
||||
"flarum/core": "^1.4"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
|
2
extensions/emoji/js/dist/forum.js
generated
vendored
2
extensions/emoji/js/dist/forum.js
generated
vendored
File diff suppressed because one or more lines are too long
2
extensions/emoji/js/dist/forum.js.map
generated
vendored
2
extensions/emoji/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -14,7 +14,7 @@
|
||||
"prettier": "^2.5.1",
|
||||
"typescript": "^4.5.4",
|
||||
"typescript-coverage-report": "^0.6.1",
|
||||
"webpack": "^5.76.0",
|
||||
"webpack": "^5.65.0",
|
||||
"webpack-cli": "^4.9.1"
|
||||
},
|
||||
"scripts": {
|
||||
|
@@ -3,7 +3,7 @@ import emojiMap from 'simple-emoji-map';
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import TextEditor from 'flarum/common/components/TextEditor';
|
||||
import TextEditorButton from 'flarum/common/components/TextEditorButton';
|
||||
import KeyboardNavigatable from 'flarum/common/utils/KeyboardNavigatable';
|
||||
import KeyboardNavigatable from 'flarum/forum/utils/KeyboardNavigatable';
|
||||
|
||||
import AutocompleteDropdown from './fragments/AutocompleteDropdown';
|
||||
import getEmojiIconCode from './helpers/getEmojiIconCode';
|
||||
@@ -80,7 +80,7 @@ export default function addComposerAutocomplete() {
|
||||
dropdown.setIndex($(this).parent().index() - 1);
|
||||
}}
|
||||
>
|
||||
<img alt={emoji} className="emoji" draggable="false" loading="lazy" src={`${cdn}72x72/${code}.png`} />
|
||||
<img alt={emoji} class="emoji" draggable="false" loading="lazy" src={`${cdn}72x72/${code}.png`} />
|
||||
{name}
|
||||
</button>
|
||||
);
|
||||
|
@@ -1,7 +0,0 @@
|
||||
import AutocompleteDropdown from './fragments/AutocompleteDropdown';
|
||||
import getEmojiIconCode from './helpers/getEmojiIconCode';
|
||||
|
||||
export default {
|
||||
'emoji/fragments/AutocompleteDropdown': AutocompleteDropdown,
|
||||
'emoji/helpers/getEmojiIconCode': getEmojiIconCode,
|
||||
};
|
@@ -11,9 +11,3 @@ app.initializers.add('flarum-emoji', () => {
|
||||
// render emoji as image in Posts content and title.
|
||||
renderEmoji();
|
||||
});
|
||||
|
||||
// Expose compat API
|
||||
import emojiCompat from './compat';
|
||||
import { compat } from '@flarum/core/forum';
|
||||
|
||||
Object.assign(compat, emojiCompat);
|
||||
|
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.8.6"
|
||||
"flarum/core": "^1.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@@ -46,7 +46,7 @@ return [
|
||||
->delete('/posts/{id}/flags', 'flags.delete', DeleteFlagsController::class),
|
||||
|
||||
(new Extend\Model(User::class))
|
||||
->cast('read_flags_at', 'datetime'),
|
||||
->dateAttribute('read_flags_at'),
|
||||
|
||||
(new Extend\Model(Post::class))
|
||||
->hasMany('flags', Flag::class, 'post_id'),
|
||||
|
4
extensions/flags/js/dist-typings/@types/shims.d.ts
generated
vendored
4
extensions/flags/js/dist-typings/@types/shims.d.ts
generated
vendored
@@ -1,7 +1,3 @@
|
||||
import 'flarum/common/models/Post';
|
||||
import 'flarum/forum/ForumApplication';
|
||||
import 'flarum/forum/components/Post';
|
||||
|
||||
import Flag from '../forum/models/Flag';
|
||||
import FlagListState from '../forum/states/FlagListState';
|
||||
import Mithril from 'mithril';
|
||||
|
4
extensions/flags/js/dist-typings/forum/compat.d.ts
generated
vendored
4
extensions/flags/js/dist-typings/forum/compat.d.ts
generated
vendored
@@ -1,4 +1,4 @@
|
||||
declare const _default: {
|
||||
declare var _default: {
|
||||
'flags/addFlagsToPosts': typeof addFlagsToPosts;
|
||||
'flags/addFlagControl': typeof addFlagControl;
|
||||
'flags/addFlagsDropdown': typeof addFlagsDropdown;
|
||||
@@ -7,7 +7,6 @@ declare const _default: {
|
||||
'flags/components/FlagPostModal': typeof FlagPostModal;
|
||||
'flags/components/FlagsPage': typeof FlagsPage;
|
||||
'flags/components/FlagsDropdown': typeof FlagsDropdown;
|
||||
'flags/states/FlagListState': typeof FlagListState;
|
||||
};
|
||||
export default _default;
|
||||
import addFlagsToPosts from "./addFlagsToPosts";
|
||||
@@ -18,4 +17,3 @@ import FlagList from "./components/FlagList";
|
||||
import FlagPostModal from "./components/FlagPostModal";
|
||||
import FlagsPage from "./components/FlagsPage";
|
||||
import FlagsDropdown from "./components/FlagsDropdown";
|
||||
import FlagListState from "./states/FlagListState";
|
||||
|
2
extensions/flags/js/dist-typings/forum/components/FlagPostModal.d.ts
generated
vendored
2
extensions/flags/js/dist-typings/forum/components/FlagPostModal.d.ts
generated
vendored
@@ -1,5 +1,5 @@
|
||||
/// <reference types="flarum/@types/translator-icu-rich" />
|
||||
export default class FlagPostModal extends Modal<import("flarum/common/components/Modal").IInternalModalAttrs, undefined> {
|
||||
export default class FlagPostModal extends Modal<import("flarum/common/components/Modal").IInternalModalAttrs> {
|
||||
constructor();
|
||||
oninit(vnode: any): void;
|
||||
success: boolean | undefined;
|
||||
|
6
extensions/flags/js/dist-typings/forum/components/FlagsDropdown.d.ts
generated
vendored
6
extensions/flags/js/dist-typings/forum/components/FlagsDropdown.d.ts
generated
vendored
@@ -1,7 +1,7 @@
|
||||
export default class FlagsDropdown extends NotificationsDropdown<import("flarum/common/components/Dropdown").IDropdownAttrs> {
|
||||
export default class FlagsDropdown {
|
||||
static initAttrs(attrs: any): void;
|
||||
constructor();
|
||||
getMenu(): JSX.Element;
|
||||
goToRoute(): void;
|
||||
getUnreadCount(): any;
|
||||
getNewCount(): unknown;
|
||||
}
|
||||
import NotificationsDropdown from "flarum/forum/components/NotificationsDropdown";
|
||||
|
2
extensions/flags/js/dist-typings/forum/extend.d.ts
generated
vendored
2
extensions/flags/js/dist-typings/forum/extend.d.ts
generated
vendored
@@ -1,2 +0,0 @@
|
||||
declare const _default: (import("flarum/common/extenders/Routes").default | import("flarum/common/extenders/Store").default | import("flarum/common/extenders/Model").default)[];
|
||||
export default _default;
|
2
extensions/flags/js/dist-typings/forum/index.d.ts
generated
vendored
2
extensions/flags/js/dist-typings/forum/index.d.ts
generated
vendored
@@ -1 +1 @@
|
||||
export { default as extend } from './extend';
|
||||
export {};
|
||||
|
2
extensions/flags/js/dist/admin.js.map
generated
vendored
2
extensions/flags/js/dist/admin.js.map
generated
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,gBAAgB,WACnCA,IAAAA,cAAAA,IACO,gBACJC,gBACC,CACEC,QAAS,8BACTC,KAAM,OACNC,MAAOJ,IAAAA,WAAAA,MAAqB,qDAE9B,IAEDC,gBAAgB,CACfC,QAAS,4BACTC,KAAM,UACNC,MAAOJ,IAAAA,WAAAA,MAAqB,sDAE7BK,mBACC,CACEC,KAAM,cACNF,MAAOJ,IAAAA,WAAAA,MAAqB,mDAC5BO,WAAY,wBAEd,WACA,IAGDF,mBACC,CACEC,KAAM,cACNF,MAAOJ,IAAAA,WAAAA,MAAqB,mDAC5BO,WAAY,wBAEd,QACA,GAEN,G","sources":["webpack://@flarum/flags/webpack/bootstrap","webpack://@flarum/flags/webpack/runtime/compat get default export","webpack://@flarum/flags/webpack/runtime/define property getters","webpack://@flarum/flags/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/flags/webpack/runtime/make namespace object","webpack://@flarum/flags/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/flags/./src/admin/index.ts"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-flags', () => {\n app.extensionData\n .for('flarum-flags')\n .registerSetting(\n {\n setting: 'flarum-flags.guidelines_url',\n type: 'text',\n label: app.translator.trans('flarum-flags.admin.settings.guidelines_url_label'),\n },\n 15\n )\n .registerSetting({\n setting: 'flarum-flags.can_flag_own',\n type: 'boolean',\n label: app.translator.trans('flarum-flags.admin.settings.flag_own_posts_label'),\n })\n .registerPermission(\n {\n icon: 'fas fa-flag',\n label: app.translator.trans('flarum-flags.admin.permissions.view_flags_label'),\n permission: 'discussion.viewFlags',\n },\n 'moderate',\n 65\n )\n\n .registerPermission(\n {\n icon: 'fas fa-flag',\n label: app.translator.trans('flarum-flags.admin.permissions.flag_posts_label'),\n permission: 'discussion.flagPosts',\n },\n 'reply',\n 65\n );\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerSetting","setting","type","label","registerPermission","icon","permission"],"sourceRoot":""}
|
||||
{"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":""}
|
2
extensions/flags/js/dist/forum.js
generated
vendored
2
extensions/flags/js/dist/forum.js
generated
vendored
File diff suppressed because one or more lines are too long
2
extensions/flags/js/dist/forum.js.map
generated
vendored
2
extensions/flags/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -7,7 +7,7 @@
|
||||
"@types/mithril": "^2.0.8",
|
||||
"prettier": "^2.5.1",
|
||||
"flarum-webpack-config": "^2.0.0",
|
||||
"webpack": "^5.76.0",
|
||||
"webpack": "^5.65.0",
|
||||
"webpack-cli": "^4.9.1",
|
||||
"@flarum/prettier-config": "^1.0.0",
|
||||
"flarum-tsconfig": "^1.0.2",
|
||||
|
4
extensions/flags/js/src/@types/shims.d.ts
vendored
4
extensions/flags/js/src/@types/shims.d.ts
vendored
@@ -1,7 +1,3 @@
|
||||
import 'flarum/common/models/Post';
|
||||
import 'flarum/forum/ForumApplication';
|
||||
import 'flarum/forum/components/Post';
|
||||
|
||||
import Flag from '../forum/models/Flag';
|
||||
import FlagListState from '../forum/states/FlagListState';
|
||||
import Mithril from 'mithril';
|
||||
|
@@ -75,7 +75,7 @@ export default function () {
|
||||
return items;
|
||||
};
|
||||
|
||||
extend(Post.prototype, 'viewItems', function (items) {
|
||||
extend(Post.prototype, 'content', function (vdom) {
|
||||
const post = this.attrs.post;
|
||||
const flags = post.flags();
|
||||
|
||||
@@ -83,8 +83,7 @@ export default function () {
|
||||
|
||||
if (post.isHidden()) this.revealContent = true;
|
||||
|
||||
items.add(
|
||||
'flagged',
|
||||
vdom.unshift(
|
||||
<div className="Post-flagged">
|
||||
<div className="Post-flagged-flags">
|
||||
{flags.map((flag) => (
|
||||
@@ -92,8 +91,7 @@ export default function () {
|
||||
))}
|
||||
</div>
|
||||
<div className="Post-flagged-actions">{this.flagActionItems().toArray()}</div>
|
||||
</div>,
|
||||
110
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -110,7 +108,7 @@ export default function () {
|
||||
user,
|
||||
reason,
|
||||
}),
|
||||
!!detail && <span className="Post-flagged-detail">{detail}</span>,
|
||||
detail ? <span className="Post-flagged-detail">{detail}</span> : '',
|
||||
];
|
||||
}
|
||||
};
|
||||
|
@@ -6,7 +6,6 @@ import FlagList from './components/FlagList';
|
||||
import FlagPostModal from './components/FlagPostModal';
|
||||
import FlagsPage from './components/FlagsPage';
|
||||
import FlagsDropdown from './components/FlagsDropdown';
|
||||
import FlagListState from './states/FlagListState';
|
||||
|
||||
export default {
|
||||
'flags/addFlagsToPosts': addFlagsToPosts,
|
||||
@@ -17,5 +16,4 @@ export default {
|
||||
'flags/components/FlagPostModal': FlagPostModal,
|
||||
'flags/components/FlagsPage': FlagsPage,
|
||||
'flags/components/FlagsDropdown': FlagsDropdown,
|
||||
'flags/states/FlagListState': FlagListState,
|
||||
};
|
||||
|
@@ -55,7 +55,7 @@ export default class FlagList extends Component {
|
||||
) : !this.state.loading ? (
|
||||
<div className="NotificationList-empty">{app.translator.trans('flarum-flags.forum.flagged_posts.empty_text')}</div>
|
||||
) : (
|
||||
<LoadingIndicator className="LoadingIndicator--block" />
|
||||
LoadingIndicator.component({ className: 'LoadingIndicator--block' })
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
|
@@ -67,13 +67,15 @@ export default class FlagPostModal extends Modal {
|
||||
<input type="radio" name="reason" checked={this.reason() === 'off_topic'} value="off_topic" onclick={withAttr('value', this.reason)} />
|
||||
<strong>{app.translator.trans('flarum-flags.forum.flag_post.reason_off_topic_label')}</strong>
|
||||
{app.translator.trans('flarum-flags.forum.flag_post.reason_off_topic_text')}
|
||||
{this.reason() === 'off_topic' && (
|
||||
{this.reason() === 'off_topic' ? (
|
||||
<textarea
|
||||
className="FormControl"
|
||||
placeholder={app.translator.trans('flarum-flags.forum.flag_post.reason_details_placeholder')}
|
||||
value={this.reasonDetail()}
|
||||
oninput={withAttr('value', this.reasonDetail)}
|
||||
></textarea>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</label>,
|
||||
70
|
||||
@@ -93,13 +95,15 @@ export default class FlagPostModal extends Modal {
|
||||
{app.translator.trans('flarum-flags.forum.flag_post.reason_inappropriate_text', {
|
||||
a: guidelinesUrl ? <a href={guidelinesUrl} target="_blank" /> : undefined,
|
||||
})}
|
||||
{this.reason() === 'inappropriate' && (
|
||||
{this.reason() === 'inappropriate' ? (
|
||||
<textarea
|
||||
className="FormControl"
|
||||
placeholder={app.translator.trans('flarum-flags.forum.flag_post.reason_details_placeholder')}
|
||||
value={this.reasonDetail()}
|
||||
oninput={withAttr('value', this.reasonDetail)}
|
||||
></textarea>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</label>,
|
||||
60
|
||||
@@ -111,13 +115,15 @@ export default class FlagPostModal extends Modal {
|
||||
<input type="radio" name="reason" checked={this.reason() === 'spam'} value="spam" onclick={withAttr('value', this.reason)} />
|
||||
<strong>{app.translator.trans('flarum-flags.forum.flag_post.reason_spam_label')}</strong>
|
||||
{app.translator.trans('flarum-flags.forum.flag_post.reason_spam_text')}
|
||||
{this.reason() === 'spam' && (
|
||||
{this.reason() === 'spam' ? (
|
||||
<textarea
|
||||
className="FormControl"
|
||||
placeholder={app.translator.trans('flarum-flags.forum.flag_post.reason_details_placeholder')}
|
||||
value={this.reasonDetail()}
|
||||
oninput={withAttr('value', this.reasonDetail)}
|
||||
></textarea>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</label>,
|
||||
50
|
||||
@@ -128,8 +134,10 @@ export default class FlagPostModal extends Modal {
|
||||
<label className="checkbox">
|
||||
<input type="radio" name="reason" checked={this.reason() === 'other'} value="other" onclick={withAttr('value', this.reason)} />
|
||||
<strong>{app.translator.trans('flarum-flags.forum.flag_post.reason_other_label')}</strong>
|
||||
{this.reason() === 'other' && (
|
||||
{this.reason() === 'other' ? (
|
||||
<textarea className="FormControl" value={this.reasonDetail()} oninput={withAttr('value', this.reasonDetail)}></textarea>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</label>,
|
||||
10
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import NotificationsDropdown from 'flarum/forum/components/NotificationsDropdown';
|
||||
import NotificationsDropdown from 'flarum/components/NotificationsDropdown';
|
||||
|
||||
import FlagList from './FlagList';
|
||||
|
||||
@@ -14,7 +14,7 @@ export default class FlagsDropdown extends NotificationsDropdown {
|
||||
getMenu() {
|
||||
return (
|
||||
<div className={'Dropdown-menu ' + this.attrs.menuClassName} onclick={this.menuClick.bind(this)}>
|
||||
{this.showing && <FlagList state={this.attrs.state} />}
|
||||
{this.showing ? FlagList.component({ state: this.attrs.state }) : ''}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@@ -1,16 +0,0 @@
|
||||
import Extend from 'flarum/common/extenders';
|
||||
import Post from 'flarum/common/models/Post';
|
||||
import FlagsPage from './components/FlagsPage';
|
||||
import Flag from './models/Flag';
|
||||
|
||||
export default [
|
||||
new Extend.Routes() //
|
||||
.add('flags', '/flags', FlagsPage),
|
||||
|
||||
new Extend.Store() //
|
||||
.add('flags', Flag),
|
||||
|
||||
new Extend.Model(Post) //
|
||||
.hasMany<Flag>('flags')
|
||||
.attribute<boolean>('canFlag'),
|
||||
];
|
@@ -1,13 +1,21 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import Model from 'flarum/common/Model';
|
||||
|
||||
import Flag from './models/Flag';
|
||||
import FlagsPage from './components/FlagsPage';
|
||||
import FlagListState from './states/FlagListState';
|
||||
import addFlagControl from './addFlagControl';
|
||||
import addFlagsDropdown from './addFlagsDropdown';
|
||||
import addFlagsToPosts from './addFlagsToPosts';
|
||||
|
||||
export { default as extend } from './extend';
|
||||
|
||||
app.initializers.add('flarum-flags', () => {
|
||||
Post.prototype.flags = Model.hasMany<Flag>('flags');
|
||||
Post.prototype.canFlag = Model.attribute<boolean>('canFlag');
|
||||
|
||||
app.store.models.flags = Flag;
|
||||
|
||||
app.routes.flags = { path: '/flags', component: FlagsPage };
|
||||
|
||||
app.flags = new FlagListState(app);
|
||||
|
||||
addFlagControl();
|
||||
@@ -18,5 +26,6 @@ app.initializers.add('flarum-flags', () => {
|
||||
// Expose compat API
|
||||
import flagsCompat from './compat';
|
||||
import { compat } from '@flarum/core/forum';
|
||||
import Post from 'flarum/common/models/Post';
|
||||
|
||||
Object.assign(compat, flagsCompat);
|
||||
|
@@ -40,7 +40,6 @@ class AddCanFlagAttribute
|
||||
// If $actor is the post author, check to see if the setting is enabled
|
||||
return (bool) $this->settings->get('flarum-flags.can_flag_own');
|
||||
}
|
||||
|
||||
// $actor is not the post author
|
||||
return true;
|
||||
}
|
||||
|
@@ -9,7 +9,6 @@
|
||||
|
||||
namespace Flarum\Flags\Api\Controller;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Flarum\Api\Controller\AbstractListController;
|
||||
use Flarum\Flags\Api\Serializer\FlagSerializer;
|
||||
use Flarum\Flags\Flag;
|
||||
@@ -44,7 +43,7 @@ class ListFlagsController extends AbstractListController
|
||||
|
||||
$actor->assertRegistered();
|
||||
|
||||
$actor->read_flags_at = Carbon::now();
|
||||
$actor->read_flags_at = time();
|
||||
$actor->save();
|
||||
|
||||
$flags = Flag::whereVisibleTo($actor)
|
||||
|
@@ -12,8 +12,6 @@ namespace Flarum\Flags\Api\Serializer;
|
||||
use Flarum\Api\Serializer\AbstractSerializer;
|
||||
use Flarum\Api\Serializer\BasicUserSerializer;
|
||||
use Flarum\Api\Serializer\PostSerializer;
|
||||
use Flarum\Flags\Flag;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class FlagSerializer extends AbstractSerializer
|
||||
{
|
||||
@@ -22,19 +20,16 @@ class FlagSerializer extends AbstractSerializer
|
||||
*/
|
||||
protected $type = 'flags';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getDefaultAttributes($flag)
|
||||
{
|
||||
if (! ($flag instanceof Flag)) {
|
||||
throw new InvalidArgumentException(
|
||||
get_class($this).' can only serialize instances of '.Flag::class
|
||||
);
|
||||
}
|
||||
|
||||
return [
|
||||
'type' => $flag->type,
|
||||
'reason' => $flag->reason,
|
||||
'type' => $flag->type,
|
||||
'reason' => $flag->reason,
|
||||
'reasonDetail' => $flag->reason_detail,
|
||||
'createdAt' => $this->formatDate($flag->created_at),
|
||||
'createdAt' => $this->formatDate($flag->created_at),
|
||||
];
|
||||
}
|
||||
|
||||
|
@@ -9,7 +9,6 @@
|
||||
|
||||
namespace Flarum\Flags\Command;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Flarum\Flags\Event\Created;
|
||||
use Flarum\Flags\Flag;
|
||||
use Flarum\Foundation\ValidationException;
|
||||
@@ -100,7 +99,7 @@ class CreateFlagHandler
|
||||
$flag->type = 'user';
|
||||
$flag->reason = Arr::get($data, 'attributes.reason');
|
||||
$flag->reason_detail = Arr::get($data, 'attributes.reasonDetail');
|
||||
$flag->created_at = Carbon::now();
|
||||
$flag->created_at = time();
|
||||
|
||||
$flag->save();
|
||||
|
||||
|
@@ -11,7 +11,7 @@ namespace Flarum\Flags\Command;
|
||||
|
||||
use Flarum\Flags\Event\Deleting;
|
||||
use Flarum\Flags\Event\FlagsWillBeDeleted;
|
||||
use Flarum\Post\Post;
|
||||
use Flarum\Flags\Flag;
|
||||
use Flarum\Post\PostRepository;
|
||||
use Illuminate\Events\Dispatcher;
|
||||
|
||||
@@ -39,7 +39,7 @@ class DeleteFlagsHandler
|
||||
|
||||
/**
|
||||
* @param DeleteFlags $command
|
||||
* @return Post
|
||||
* @return Flag
|
||||
*/
|
||||
public function handle(DeleteFlags $command)
|
||||
{
|
||||
|
@@ -9,23 +9,11 @@
|
||||
|
||||
namespace Flarum\Flags;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Flarum\Database\AbstractModel;
|
||||
use Flarum\Database\ScopeVisibilityTrait;
|
||||
use Flarum\Post\Post;
|
||||
use Flarum\User\User;
|
||||
|
||||
/**
|
||||
* @property int $post_id
|
||||
* @property int $user_id
|
||||
* @property string $type
|
||||
* @property string $reason
|
||||
* @property string $reason_detail
|
||||
* @property Carbon $created_at
|
||||
*
|
||||
* @property-read Post $post
|
||||
* @property-read User $user
|
||||
*/
|
||||
class Flag extends AbstractModel
|
||||
{
|
||||
use ScopeVisibilityTrait;
|
||||
|
@@ -7,7 +7,7 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"flarum/core": "^1.8"
|
||||
"flarum/core": "^1.4"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
|
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.8"
|
||||
"flarum/core": "^1.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@@ -13,15 +13,12 @@ use Flarum\Api\Controller;
|
||||
use Flarum\Api\Serializer\BasicUserSerializer;
|
||||
use Flarum\Api\Serializer\PostSerializer;
|
||||
use Flarum\Extend;
|
||||
use Flarum\Likes\Api\LoadLikesRelationship;
|
||||
use Flarum\Likes\Event\PostWasLiked;
|
||||
use Flarum\Likes\Event\PostWasUnliked;
|
||||
use Flarum\Likes\Notification\PostLikedBlueprint;
|
||||
use Flarum\Likes\Query\LikedByFilter;
|
||||
use Flarum\Likes\Query\LikedFilter;
|
||||
use Flarum\Post\Filter\PostFilterer;
|
||||
use Flarum\Post\Post;
|
||||
use Flarum\User\Filter\UserFilterer;
|
||||
use Flarum\User\User;
|
||||
|
||||
return [
|
||||
@@ -44,32 +41,19 @@ return [
|
||||
->hasMany('likes', BasicUserSerializer::class)
|
||||
->attribute('canLike', function (PostSerializer $serializer, $model) {
|
||||
return (bool) $serializer->getActor()->can('like', $model);
|
||||
})
|
||||
->attribute('likesCount', function (PostSerializer $serializer, $model) {
|
||||
return $model->getAttribute('likes_count') ?: 0;
|
||||
}),
|
||||
|
||||
(new Extend\ApiController(Controller\ShowDiscussionController::class))
|
||||
->addInclude('posts.likes')
|
||||
->loadWhere('posts.likes', [LoadLikesRelationship::class, 'mutateRelation'])
|
||||
->prepareDataForSerialization([LoadLikesRelationship::class, 'countRelation']),
|
||||
->addInclude('posts.likes'),
|
||||
|
||||
(new Extend\ApiController(Controller\ListPostsController::class))
|
||||
->addInclude('likes')
|
||||
->loadWhere('likes', [LoadLikesRelationship::class, 'mutateRelation'])
|
||||
->prepareDataForSerialization([LoadLikesRelationship::class, 'countRelation']),
|
||||
->addInclude('likes'),
|
||||
(new Extend\ApiController(Controller\ShowPostController::class))
|
||||
->addInclude('likes')
|
||||
->loadWhere('likes', [LoadLikesRelationship::class, 'mutateRelation'])
|
||||
->prepareDataForSerialization([LoadLikesRelationship::class, 'countRelation']),
|
||||
->addInclude('likes'),
|
||||
(new Extend\ApiController(Controller\CreatePostController::class))
|
||||
->addInclude('likes')
|
||||
->loadWhere('likes', [LoadLikesRelationship::class, 'mutateRelation'])
|
||||
->prepareDataForSerialization([LoadLikesRelationship::class, 'countRelation']),
|
||||
->addInclude('likes'),
|
||||
(new Extend\ApiController(Controller\UpdatePostController::class))
|
||||
->addInclude('likes')
|
||||
->loadWhere('likes', [LoadLikesRelationship::class, 'mutateRelation'])
|
||||
->prepareDataForSerialization([LoadLikesRelationship::class, 'countRelation']),
|
||||
->addInclude('likes'),
|
||||
|
||||
(new Extend\Event())
|
||||
->listen(PostWasLiked::class, Listener\SendNotificationWhenPostIsLiked::class)
|
||||
@@ -79,9 +63,6 @@ return [
|
||||
(new Extend\Filter(PostFilterer::class))
|
||||
->addFilter(LikedByFilter::class),
|
||||
|
||||
(new Extend\Filter(UserFilterer::class))
|
||||
->addFilter(LikedFilter::class),
|
||||
|
||||
(new Extend\Settings())
|
||||
->default('flarum-likes.like_own_post', true),
|
||||
|
||||
|
2
extensions/likes/js/dist/admin.js.map
generated
vendored
2
extensions/likes/js/dist/admin.js.map
generated
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"admin.js","mappings":"MACA,IAAIA,EAAsB,CCA1BA,EAAyBC,IACxB,IAAIC,EAASD,GAAUA,EAAOE,WAC7B,IAAOF,EAAiB,QACxB,IAAM,EAEP,OADAD,EAAoBI,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdF,EAAwB,CAACM,EAASC,KACjC,IAAI,IAAIC,KAAOD,EACXP,EAAoBS,EAAEF,EAAYC,KAASR,EAAoBS,EAAEH,EAASE,IAC5EE,OAAOC,eAAeL,EAASE,EAAK,CAAEI,YAAY,EAAMC,IAAKN,EAAWC,IAE1E,ECNDR,EAAwB,CAACc,EAAKC,IAAUL,OAAOM,UAAUC,eAAeC,KAAKJ,EAAKC,GCClFf,EAAyBM,IACH,oBAAXa,QAA0BA,OAAOC,aAC1CV,OAAOC,eAAeL,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DX,OAAOC,eAAeL,EAAS,aAAc,CAAEe,OAAO,GAAO,G,+BCL9D,MAAM,EAA+BC,OAAOC,KAAKC,OAAO,a,aCExDC,IAAAA,aAAAA,IAAqB,gBAAgB,WACnCA,IAAAA,cAAAA,IACO,gBACJC,mBACC,CACEC,KAAM,mBACNC,MAAOH,IAAAA,WAAAA,MAAqB,mDAC5BI,WAAY,wBAEd,SAEDC,gBAAgB,CACfC,QAAS,6BACTC,KAAM,OACNJ,MAAOH,IAAAA,WAAAA,MAAqB,oDAC5BQ,KAAMR,IAAAA,WAAAA,MAAqB,oDAEjC,G","sources":["webpack://@flarum/likes/webpack/bootstrap","webpack://@flarum/likes/webpack/runtime/compat get default export","webpack://@flarum/likes/webpack/runtime/define property getters","webpack://@flarum/likes/webpack/runtime/hasOwnProperty shorthand","webpack://@flarum/likes/webpack/runtime/make namespace object","webpack://@flarum/likes/external root \"flarum.core.compat['admin/app']\"","webpack://@flarum/likes/./src/admin/index.js"],"sourcesContent":["// The require scope\nvar __webpack_require__ = {};\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","const __WEBPACK_NAMESPACE_OBJECT__ = flarum.core.compat['admin/app'];","import app from 'flarum/admin/app';\n\napp.initializers.add('flarum-likes', () => {\n app.extensionData\n .for('flarum-likes')\n .registerPermission(\n {\n icon: 'far fa-thumbs-up',\n label: app.translator.trans('flarum-likes.admin.permissions.like_posts_label'),\n permission: 'discussion.likePosts',\n },\n 'reply'\n )\n .registerSetting({\n setting: 'flarum-likes.like_own_post',\n type: 'bool',\n label: app.translator.trans('flarum-likes.admin.settings.like_own_posts_label'),\n help: app.translator.trans('flarum-likes.admin.settings.like_own_posts_help'),\n });\n});\n"],"names":["__webpack_require__","module","getter","__esModule","d","a","exports","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","flarum","core","compat","app","registerPermission","icon","label","permission","registerSetting","setting","type","help"],"sourceRoot":""}
|
||||
{"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":""}
|
2
extensions/likes/js/dist/forum.js
generated
vendored
2
extensions/likes/js/dist/forum.js
generated
vendored
File diff suppressed because one or more lines are too long
2
extensions/likes/js/dist/forum.js.map
generated
vendored
2
extensions/likes/js/dist/forum.js.map
generated
vendored
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
|
||||
"devDependencies": {
|
||||
"prettier": "^2.5.1",
|
||||
"flarum-webpack-config": "^2.0.0",
|
||||
"webpack": "^5.76.0",
|
||||
"webpack": "^5.65.0",
|
||||
"webpack-cli": "^4.9.1",
|
||||
"@flarum/prettier-config": "^1.0.0"
|
||||
},
|
||||
|
11
extensions/likes/js/src/@types/shims.d.ts
vendored
11
extensions/likes/js/src/@types/shims.d.ts
vendored
@@ -1,11 +0,0 @@
|
||||
import 'flarum/common/models/Post';
|
||||
|
||||
import User from 'flarum/common/models/User';
|
||||
|
||||
declare module 'flarum/common/models/Post' {
|
||||
export default interface Post {
|
||||
likes(): User[];
|
||||
likesCount(): number;
|
||||
canLike(): boolean;
|
||||
}
|
||||
}
|
@@ -15,31 +15,32 @@ export default function () {
|
||||
|
||||
items.add(
|
||||
'like',
|
||||
<Button
|
||||
className="Button Button--link"
|
||||
onclick={() => {
|
||||
isLiked = !isLiked;
|
||||
Button.component(
|
||||
{
|
||||
className: 'Button Button--link',
|
||||
onclick: () => {
|
||||
isLiked = !isLiked;
|
||||
|
||||
post.save({ isLiked });
|
||||
post.save({ isLiked });
|
||||
|
||||
// We've saved the fact that we do or don't like the post, but in order
|
||||
// to provide instantaneous feedback to the user, we'll need to add or
|
||||
// remove the like from the relationship data manually.
|
||||
const data = post.data.relationships.likes.data;
|
||||
data.some((like, i) => {
|
||||
if (like.id === app.session.user.id()) {
|
||||
data.splice(i, 1);
|
||||
return true;
|
||||
// We've saved the fact that we do or don't like the post, but in order
|
||||
// to provide instantaneous feedback to the user, we'll need to add or
|
||||
// remove the like from the relationship data manually.
|
||||
const data = post.data.relationships.likes.data;
|
||||
data.some((like, i) => {
|
||||
if (like.id === app.session.user.id()) {
|
||||
data.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (isLiked) {
|
||||
data.unshift({ type: 'users', id: app.session.user.id() });
|
||||
}
|
||||
});
|
||||
|
||||
if (isLiked) {
|
||||
data.unshift({ type: 'users', id: app.session.user.id() });
|
||||
}
|
||||
}}
|
||||
>
|
||||
{app.translator.trans(isLiked ? 'flarum-likes.forum.post.unlike_link' : 'flarum-likes.forum.post.like_link')}
|
||||
</Button>
|
||||
},
|
||||
},
|
||||
app.translator.trans(isLiked ? 'flarum-likes.forum.post.unlike_link' : 'flarum-likes.forum.post.like_link')
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@ import Link from 'flarum/common/components/Link';
|
||||
import punctuateSeries from 'flarum/common/helpers/punctuateSeries';
|
||||
import username from 'flarum/common/helpers/username';
|
||||
import icon from 'flarum/common/helpers/icon';
|
||||
import Button from 'flarum/common/components/Button';
|
||||
|
||||
import PostLikesModal from './components/PostLikesModal';
|
||||
|
||||
@@ -16,7 +15,7 @@ export default function () {
|
||||
|
||||
if (likes && likes.length) {
|
||||
const limit = 4;
|
||||
const overLimit = post.likesCount() > limit;
|
||||
const overLimit = likes.length > limit;
|
||||
|
||||
// Construct a list of names of users who have liked this post. Make sure the
|
||||
// current user is first in the list, and cap a maximum of 4 items.
|
||||
@@ -35,31 +34,26 @@ export default function () {
|
||||
// others" name to the end of the list. Clicking on it will display a modal
|
||||
// with a full list of names.
|
||||
if (overLimit) {
|
||||
const count = post.likesCount() - names.length;
|
||||
const label = app.translator.trans('flarum-likes.forum.post.others_link', { count });
|
||||
const count = likes.length - names.length;
|
||||
|
||||
if (app.forum.attribute('canSearchUsers')) {
|
||||
names.push(
|
||||
<Button
|
||||
className="Button Button--ua-reset Button--text"
|
||||
onclick={(e) => {
|
||||
e.preventDefault();
|
||||
app.modal.show(PostLikesModal, { post });
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</Button>
|
||||
);
|
||||
} else {
|
||||
names.push(<span>{label}</span>);
|
||||
}
|
||||
names.push(
|
||||
<a
|
||||
href="#"
|
||||
onclick={(e) => {
|
||||
e.preventDefault();
|
||||
app.modal.show(PostLikesModal, { post });
|
||||
}}
|
||||
>
|
||||
{app.translator.trans('flarum-likes.forum.post.others_link', { count })}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
items.add(
|
||||
'liked',
|
||||
<div className="Post-likedBy">
|
||||
{icon('far fa-thumbs-up')}
|
||||
{app.translator.trans(`flarum-likes.forum.post.liked_by${likes[0] === app.session.user ? '_self' : ''}_text`, {
|
||||
{app.translator.trans('flarum-likes.forum.post.liked_by' + (likes[0] === app.session.user ? '_self' : '') + '_text', {
|
||||
count: names.length,
|
||||
users: punctuateSeries(names),
|
||||
})}
|
||||
|
@@ -2,15 +2,17 @@ import { extend } from 'flarum/common/extend';
|
||||
import app from 'flarum/forum/app';
|
||||
import UserPage from 'flarum/forum/components/UserPage';
|
||||
import LinkButton from 'flarum/common/components/LinkButton';
|
||||
import LikesUserPage from './components/LikesUserPage';
|
||||
import ItemList from 'flarum/common/utils/ItemList';
|
||||
import type Mithril from 'mithril';
|
||||
|
||||
export default function addLikesTabToUserProfile() {
|
||||
app.routes['user.likes'] = { path: '/u/:username/likes', component: LikesUserPage };
|
||||
extend(UserPage.prototype, 'navItems', function (items: ItemList<Mithril.Children>) {
|
||||
const user = this.user;
|
||||
items.add(
|
||||
'likes',
|
||||
<LinkButton href={app.route('user.likes', { username: user?.slug() })} icon="far fa-thumbs-up">
|
||||
<LinkButton href={app.route('user.likes', { username: user.slug() })} icon="far fa-thumbs-up">
|
||||
{app.translator.trans('flarum-likes.forum.user.likes_link')}
|
||||
</LinkButton>,
|
||||
88
|
||||
|
@@ -1,11 +0,0 @@
|
||||
import LikesUserPage from './components/LikesUserPage';
|
||||
import PostLikedNotification from './components/PostLikedNotification';
|
||||
import PostLikesModal from './components/PostLikesModal';
|
||||
import PostLikesModalState from './states/PostLikesModalState';
|
||||
|
||||
export default {
|
||||
'likes/components/LikesUserPage': LikesUserPage,
|
||||
'likes/components/PostLikedNotification': PostLikedNotification,
|
||||
'likes/components/PostLikesModal': PostLikesModal,
|
||||
'likes/states/PostLikesModalState': PostLikesModalState,
|
||||
};
|
31
extensions/likes/js/src/forum/components/PostLikesModal.js
Normal file
31
extensions/likes/js/src/forum/components/PostLikesModal.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import Modal from 'flarum/common/components/Modal';
|
||||
import Link from 'flarum/common/components/Link';
|
||||
import avatar from 'flarum/common/helpers/avatar';
|
||||
import username from 'flarum/common/helpers/username';
|
||||
|
||||
export default class PostLikesModal extends Modal {
|
||||
className() {
|
||||
return 'PostLikesModal Modal--small';
|
||||
}
|
||||
|
||||
title() {
|
||||
return app.translator.trans('flarum-likes.forum.post_likes.title');
|
||||
}
|
||||
|
||||
content() {
|
||||
return (
|
||||
<div className="Modal-body">
|
||||
<ul className="PostLikesModal-list">
|
||||
{this.attrs.post.likes().map((user) => (
|
||||
<li>
|
||||
<Link href={app.route.user(user)}>
|
||||
{avatar(user)} {username(user)}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,72 +0,0 @@
|
||||
import app from 'flarum/forum/app';
|
||||
import Modal from 'flarum/common/components/Modal';
|
||||
import Link from 'flarum/common/components/Link';
|
||||
import avatar from 'flarum/common/helpers/avatar';
|
||||
import username from 'flarum/common/helpers/username';
|
||||
import type { IInternalModalAttrs } from 'flarum/common/components/Modal';
|
||||
import type Post from 'flarum/common/models/Post';
|
||||
import type Mithril from 'mithril';
|
||||
import PostLikesModalState from '../states/PostLikesModalState';
|
||||
import Button from 'flarum/common/components/Button';
|
||||
import LoadingIndicator from 'flarum/common/components/LoadingIndicator';
|
||||
|
||||
export interface IPostLikesModalAttrs extends IInternalModalAttrs {
|
||||
post: Post;
|
||||
}
|
||||
|
||||
export default class PostLikesModal<CustomAttrs extends IPostLikesModalAttrs = IPostLikesModalAttrs> extends Modal<CustomAttrs, PostLikesModalState> {
|
||||
oninit(vnode: Mithril.VnodeDOM<CustomAttrs, this>) {
|
||||
super.oninit(vnode);
|
||||
|
||||
this.state = new PostLikesModalState({
|
||||
filter: {
|
||||
liked: this.attrs.post.id()!,
|
||||
},
|
||||
});
|
||||
|
||||
this.state.refresh();
|
||||
}
|
||||
|
||||
className() {
|
||||
return 'PostLikesModal Modal--small';
|
||||
}
|
||||
|
||||
title() {
|
||||
return app.translator.trans('flarum-likes.forum.post_likes.title');
|
||||
}
|
||||
|
||||
content() {
|
||||
return (
|
||||
<>
|
||||
<div className="Modal-body">
|
||||
{this.state.isInitialLoading() ? (
|
||||
<LoadingIndicator />
|
||||
) : (
|
||||
<ul className="PostLikesModal-list">
|
||||
{this.state.getPages().map((page) =>
|
||||
page.items.map((user) => (
|
||||
<li>
|
||||
<Link href={app.route.user(user)}>
|
||||
{avatar(user)} {username(user)}
|
||||
</Link>
|
||||
</li>
|
||||
))
|
||||
)}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
{this.state.hasNext() ? (
|
||||
<div className="Modal-footer">
|
||||
<div className="Form Form--centered">
|
||||
<div className="Form-group">
|
||||
<Button className="Button Button--block" onclick={() => this.state.loadNext()} loading={this.state.isLoadingNext()}>
|
||||
{app.translator.trans('flarum-likes.forum.post_likes.load_more_button')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
import Extend from 'flarum/common/extenders';
|
||||
import Post from 'flarum/common/models/Post';
|
||||
import User from 'flarum/common/models/User';
|
||||
import LikesUserPage from './components/LikesUserPage';
|
||||
|
||||
export default [
|
||||
new Extend.Routes() //
|
||||
.add('user.likes', '/u/:username/likes', LikesUserPage),
|
||||
|
||||
new Extend.Model(Post) //
|
||||
.hasMany<User>('likes')
|
||||
.attribute<number>('likesCount')
|
||||
.attribute<boolean>('canLike'),
|
||||
];
|
@@ -1,5 +1,7 @@
|
||||
import { extend } from 'flarum/common/extend';
|
||||
import app from 'flarum/forum/app';
|
||||
import Post from 'flarum/common/models/Post';
|
||||
import Model from 'flarum/common/Model';
|
||||
import NotificationGrid from 'flarum/forum/components/NotificationGrid';
|
||||
|
||||
import addLikeAction from './addLikeAction';
|
||||
@@ -7,11 +9,12 @@ import addLikesList from './addLikesList';
|
||||
import PostLikedNotification from './components/PostLikedNotification';
|
||||
import addLikesTabToUserProfile from './addLikesTabToUserProfile';
|
||||
|
||||
export { default as extend } from './extend';
|
||||
|
||||
app.initializers.add('flarum-likes', () => {
|
||||
app.notificationComponents.postLiked = PostLikedNotification;
|
||||
|
||||
Post.prototype.canLike = Model.attribute('canLike');
|
||||
Post.prototype.likes = Model.hasMany('likes');
|
||||
|
||||
addLikeAction();
|
||||
addLikesList();
|
||||
addLikesTabToUserProfile();
|
||||
@@ -24,9 +27,3 @@ app.initializers.add('flarum-likes', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Expose compat API
|
||||
import likesCompat from './compat';
|
||||
import { compat } from '@flarum/core/forum';
|
||||
|
||||
Object.assign(compat, likesCompat);
|
||||
|
@@ -1,26 +0,0 @@
|
||||
import PaginatedListState, { PaginatedListParams } from 'flarum/common/states/PaginatedListState';
|
||||
import User from 'flarum/common/models/User';
|
||||
|
||||
export interface PostLikesModalListParams extends PaginatedListParams {
|
||||
filter: {
|
||||
liked: string;
|
||||
};
|
||||
page?: {
|
||||
offset?: number;
|
||||
limit: number;
|
||||
};
|
||||
}
|
||||
|
||||
export default class PostLikesModalState<P extends PostLikesModalListParams = PostLikesModalListParams> extends PaginatedListState<User, P> {
|
||||
constructor(params: P, page: number = 1) {
|
||||
const limit = 10;
|
||||
|
||||
params.page = { ...(params.page || {}), limit };
|
||||
|
||||
super(params, page, limit);
|
||||
}
|
||||
|
||||
get type(): string {
|
||||
return 'users';
|
||||
}
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
{
|
||||
// Use Flarum's tsconfig as a starting point
|
||||
"extends": "flarum-tsconfig",
|
||||
// This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder
|
||||
// and also tells your Typescript server to read core's global typings for
|
||||
// access to `dayjs` and `$` in the global namespace.
|
||||
"include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"],
|
||||
"compilerOptions": {
|
||||
// This will output typings to `dist-typings`
|
||||
"declarationDir": "./dist-typings",
|
||||
"paths": {
|
||||
"flarum/*": ["../../../framework/core/js/dist-typings/*"],
|
||||
// TODO: remove after export registry system implemented
|
||||
// Without this, the old-style `@flarum/core` import is resolved to
|
||||
// source code in flarum/core instead of the dist typings.
|
||||
// This causes an inaccurate "duplicate export" error.
|
||||
"@flarum/core/*": ["../../../framework/core/js/dist-typings/*"],
|
||||
}
|
||||
}
|
||||
}
|
@@ -35,7 +35,6 @@ flarum-likes:
|
||||
# These translations are used by the Users Who Like This modal dialog.
|
||||
post_likes:
|
||||
title: Users Who Like This
|
||||
load_more_button: => core.ref.load_more
|
||||
|
||||
# These translations are used in the Settings page.
|
||||
settings:
|
||||
|
@@ -1,60 +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\Likes\Api;
|
||||
|
||||
use Flarum\Discussion\Discussion;
|
||||
use Flarum\Http\RequestUtil;
|
||||
use Flarum\Post\Post;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class LoadLikesRelationship
|
||||
{
|
||||
public static $maxLikes = 4;
|
||||
|
||||
public static function mutateRelation(BelongsToMany $query, ServerRequestInterface $request): BelongsToMany
|
||||
{
|
||||
$actor = RequestUtil::getActor($request);
|
||||
|
||||
$grammar = $query->getQuery()->getGrammar();
|
||||
|
||||
return $query
|
||||
// So that we can tell if the current user has liked the post.
|
||||
->orderBy(new Expression($grammar->wrap('user_id').' = '.$actor->id), 'desc')
|
||||
// Limiting a relationship results is only possible because
|
||||
// the Post model uses the \Staudenmeir\EloquentEagerLimit\HasEagerLimit
|
||||
// trait.
|
||||
->limit(self::$maxLikes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called using the @see ApiController::prepareDataForSerialization extender.
|
||||
*/
|
||||
public static function countRelation($controller, $data): void
|
||||
{
|
||||
$loadable = null;
|
||||
|
||||
if ($data instanceof Discussion) {
|
||||
$loadable = $data->newCollection($data->posts)->filter(function ($post) {
|
||||
return $post instanceof Post;
|
||||
});
|
||||
} elseif ($data instanceof Collection) {
|
||||
$loadable = $data;
|
||||
} elseif ($data instanceof Post) {
|
||||
$loadable = $data->newCollection([$data]);
|
||||
}
|
||||
|
||||
if ($loadable) {
|
||||
$loadable->loadCount('likes');
|
||||
}
|
||||
}
|
||||
}
|
@@ -11,20 +11,17 @@ namespace Flarum\Likes\Query;
|
||||
|
||||
use Flarum\Filter\FilterInterface;
|
||||
use Flarum\Filter\FilterState;
|
||||
use Flarum\Filter\ValidateFilterTrait;
|
||||
|
||||
class LikedByFilter implements FilterInterface
|
||||
{
|
||||
use ValidateFilterTrait;
|
||||
|
||||
public function getFilterKey(): string
|
||||
{
|
||||
return 'likedBy';
|
||||
}
|
||||
|
||||
public function filter(FilterState $filterState, $filterValue, bool $negate)
|
||||
public function filter(FilterState $filterState, string $filterValue, bool $negate)
|
||||
{
|
||||
$likedId = $this->asInt($filterValue);
|
||||
$likedId = trim($filterValue, '"');
|
||||
|
||||
$filterState
|
||||
->getQuery()
|
||||
|
@@ -1,34 +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\Likes\Query;
|
||||
|
||||
use Flarum\Filter\FilterInterface;
|
||||
use Flarum\Filter\FilterState;
|
||||
|
||||
class LikedFilter implements FilterInterface
|
||||
{
|
||||
public function getFilterKey(): string
|
||||
{
|
||||
return 'liked';
|
||||
}
|
||||
|
||||
public function filter(FilterState $filterState, string $filterValue, bool $negate)
|
||||
{
|
||||
$likedId = trim($filterValue, '"');
|
||||
|
||||
$filterState
|
||||
->getQuery()
|
||||
->whereIn('id', function ($query) use ($likedId) {
|
||||
$query->select('user_id')
|
||||
->from('post_likes')
|
||||
->where('post_id', $likedId);
|
||||
}, 'and', $negate);
|
||||
}
|
||||
}
|
@@ -1,210 +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\Likes\Tests\integration\api\discussions;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Flarum\Group\Group;
|
||||
use Flarum\Likes\Api\LoadLikesRelationship;
|
||||
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
|
||||
use Flarum\Testing\integration\TestCase;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class ListPostsTest extends TestCase
|
||||
{
|
||||
use RetrievesAuthorizedUsers;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->extension('flarum-likes');
|
||||
|
||||
$this->prepareDatabase([
|
||||
'discussions' => [
|
||||
['id' => 100, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'user_id' => 1, 'first_post_id' => 101, 'comment_count' => 1],
|
||||
],
|
||||
'posts' => [
|
||||
['id' => 101, 'discussion_id' => 100, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>text</p></t>'],
|
||||
],
|
||||
'users' => [
|
||||
$this->normalUser(),
|
||||
['id' => 102, 'username' => 'user102', 'email' => '102@machine.local', 'is_email_confirmed' => 1],
|
||||
['id' => 103, 'username' => 'user103', 'email' => '103@machine.local', 'is_email_confirmed' => 1],
|
||||
['id' => 104, 'username' => 'user104', 'email' => '104@machine.local', 'is_email_confirmed' => 1],
|
||||
['id' => 105, 'username' => 'user105', 'email' => '105@machine.local', 'is_email_confirmed' => 1],
|
||||
['id' => 106, 'username' => 'user106', 'email' => '106@machine.local', 'is_email_confirmed' => 1],
|
||||
['id' => 107, 'username' => 'user107', 'email' => '107@machine.local', 'is_email_confirmed' => 1],
|
||||
['id' => 108, 'username' => 'user108', 'email' => '108@machine.local', 'is_email_confirmed' => 1],
|
||||
['id' => 109, 'username' => 'user109', 'email' => '109@machine.local', 'is_email_confirmed' => 1],
|
||||
['id' => 110, 'username' => 'user110', 'email' => '110@machine.local', 'is_email_confirmed' => 1],
|
||||
['id' => 111, 'username' => 'user111', 'email' => '111@machine.local', 'is_email_confirmed' => 1],
|
||||
['id' => 112, 'username' => 'user112', 'email' => '112@machine.local', 'is_email_confirmed' => 1],
|
||||
],
|
||||
'post_likes' => [
|
||||
['user_id' => 102, 'post_id' => 101],
|
||||
['user_id' => 104, 'post_id' => 101],
|
||||
['user_id' => 105, 'post_id' => 101],
|
||||
['user_id' => 106, 'post_id' => 101],
|
||||
['user_id' => 107, 'post_id' => 101],
|
||||
['user_id' => 108, 'post_id' => 101],
|
||||
['user_id' => 109, 'post_id' => 101],
|
||||
['user_id' => 110, 'post_id' => 101],
|
||||
['user_id' => 2, 'post_id' => 101],
|
||||
['user_id' => 111, 'post_id' => 101],
|
||||
['user_id' => 112, 'post_id' => 101],
|
||||
],
|
||||
'group_permission' => [
|
||||
['group_id' => Group::GUEST_ID, 'permission' => 'searchUsers'],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function liked_filter_works()
|
||||
{
|
||||
$response = $this->send(
|
||||
$this->request('GET', '/api/users')
|
||||
->withQueryParams([
|
||||
'filter' => ['liked' => 101],
|
||||
])
|
||||
);
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
|
||||
$data = json_decode($response->getBody()->getContents(), true)['data'];
|
||||
|
||||
// Order-independent comparison
|
||||
$ids = Arr::pluck($data, 'id');
|
||||
$this->assertEqualsCanonicalizing([
|
||||
102, 104, 105, 106, 107, 108, 109, 110, 2, 111, 112
|
||||
], $ids, 'IDs do not match');
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function liked_filter_works_negated()
|
||||
{
|
||||
$response = $this->send(
|
||||
$this->request('GET', '/api/users')
|
||||
->withQueryParams([
|
||||
'filter' => ['-liked' => 101],
|
||||
])
|
||||
);
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
|
||||
$data = json_decode($response->getBody()->getContents(), true)['data'];
|
||||
|
||||
// Order-independent comparison
|
||||
$ids = Arr::pluck($data, 'id');
|
||||
$this->assertEqualsCanonicalizing([1, 103], $ids, 'IDs do not match');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function likes_relation_returns_limited_results_and_shows_only_visible_posts_in_show_post_endpoint()
|
||||
{
|
||||
// List posts endpoint
|
||||
$response = $this->send(
|
||||
$this->request('GET', '/api/posts/101', [
|
||||
'authenticatedAs' => 2,
|
||||
])->withQueryParams([
|
||||
'include' => 'likes',
|
||||
])
|
||||
);
|
||||
|
||||
$data = json_decode($response->getBody()->getContents(), true)['data'];
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
|
||||
$likes = $data['relationships']['likes']['data'];
|
||||
|
||||
// Only displays a limited amount of likes
|
||||
$this->assertCount(LoadLikesRelationship::$maxLikes, $likes);
|
||||
// Displays the correct count of likes
|
||||
$this->assertEquals(11, $data['attributes']['likesCount']);
|
||||
// Of the limited amount of likes, the actor always appears
|
||||
$this->assertEquals([2, 102, 104, 105], Arr::pluck($likes, 'id'));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function likes_relation_returns_limited_results_and_shows_only_visible_posts_in_list_posts_endpoint()
|
||||
{
|
||||
// List posts endpoint
|
||||
$response = $this->send(
|
||||
$this->request('GET', '/api/posts', [
|
||||
'authenticatedAs' => 2,
|
||||
])->withQueryParams([
|
||||
'filter' => ['discussion' => 100],
|
||||
'include' => 'likes',
|
||||
])
|
||||
);
|
||||
|
||||
$data = json_decode($response->getBody()->getContents(), true)['data'];
|
||||
|
||||
$this->assertEquals(200, $response->getStatusCode());
|
||||
|
||||
$likes = $data[0]['relationships']['likes']['data'];
|
||||
|
||||
// Only displays a limited amount of likes
|
||||
$this->assertCount(LoadLikesRelationship::$maxLikes, $likes);
|
||||
// Displays the correct count of likes
|
||||
$this->assertEquals(11, $data[0]['attributes']['likesCount']);
|
||||
// Of the limited amount of likes, the actor always appears
|
||||
$this->assertEquals([2, 102, 104, 105], Arr::pluck($likes, 'id'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider likesIncludeProvider
|
||||
* @test
|
||||
*/
|
||||
public function likes_relation_returns_limited_results_and_shows_only_visible_posts_in_show_discussion_endpoint(string $include)
|
||||
{
|
||||
// Show discussion endpoint
|
||||
$response = $this->send(
|
||||
$this->request('GET', '/api/discussions/100', [
|
||||
'authenticatedAs' => 2,
|
||||
])->withQueryParams([
|
||||
'include' => $include,
|
||||
])
|
||||
);
|
||||
|
||||
$included = json_decode($response->getBody()->getContents(), true)['included'];
|
||||
|
||||
$likes = collect($included)
|
||||
->where('type', 'posts')
|
||||
->where('id', 101)
|
||||
->first()['relationships']['likes']['data'];
|
||||
|
||||
// Only displays a limited amount of likes
|
||||
$this->assertCount(LoadLikesRelationship::$maxLikes, $likes);
|
||||
// Displays the correct count of likes
|
||||
$this->assertEquals(11, collect($included)
|
||||
->where('type', 'posts')
|
||||
->where('id', 101)
|
||||
->first()['attributes']['likesCount']);
|
||||
// Of the limited amount of likes, the actor always appears
|
||||
$this->assertEquals([2, 102, 104, 105], Arr::pluck($likes, 'id'));
|
||||
}
|
||||
|
||||
public function likesIncludeProvider(): array
|
||||
{
|
||||
return [
|
||||
['posts,posts.likes'],
|
||||
['posts.likes'],
|
||||
[''],
|
||||
];
|
||||
}
|
||||
}
|
@@ -19,7 +19,7 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"flarum/core": "^1.8"
|
||||
"flarum/core": "^1.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@@ -35,15 +35,12 @@ return [
|
||||
(new Extend\Notification())
|
||||
->type(DiscussionLockedBlueprint::class, BasicDiscussionSerializer::class, ['alert']),
|
||||
|
||||
(new Extend\Model(Discussion::class))
|
||||
->cast('is_locked', 'bool'),
|
||||
|
||||
(new Extend\ApiSerializer(DiscussionSerializer::class))
|
||||
->attribute('isLocked', function (DiscussionSerializer $serializer, Discussion $discussion) {
|
||||
return $discussion->is_locked;
|
||||
return (bool) $discussion->is_locked;
|
||||
})
|
||||
->attribute('canLock', function (DiscussionSerializer $serializer, Discussion $discussion) {
|
||||
return $serializer->getActor()->can('lock', $discussion);
|
||||
return (bool) $serializer->getActor()->can('lock', $discussion);
|
||||
}),
|
||||
|
||||
(new Extend\Post())
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user