1
0
mirror of https://github.com/flarum/core.git synced 2025-08-13 20:04:24 +02:00

Compare commits

...

17 Commits

Author SHA1 Message Date
Daniël Klabbers
556d461cfb chore: update v1.4 constraints and update issues url 2022-07-12 23:30:03 +02:00
Daniël Klabbers
6cfebe381a chore: update version constant for the v1.4 release 2022-07-12 23:29:45 +02:00
Daniël Klabbers
8ab2827f4c chore: add changelog for v1.4 2022-07-12 23:27:03 +02:00
Sami Mazouz
024155a608 test(likes): like action behavior (#3512)
Signed-off-by: Sami Mazouz <ilyasmazouz@gmail.com>
2022-07-11 10:42:21 +01:00
Sami Mazouz
4da21463c1 fix: multiple createdAt columns in query causes conflicts (#3506)
* test: list posts with mentions filter and `createdAt` sort
* fix: multiple `createdAt` columns in query causes conflicts
* chore: link to pull request for context

Signed-off-by: Sami Mazouz <ilyasmazouz@gmail.com>
2022-07-09 10:36:48 +01:00
Sami Mazouz
abc12b4ba5 chore: add .gitattributes to extensions to export-ignore files. (#3513)
Signed-off-by: Sami Mazouz <ilyasmazouz@gmail.com>
2022-07-08 20:38:20 +01:00
Sami Mazouz
d8d4eae9f5 test(suspend): test that suspension works as expected (#3511)
Signed-off-by: Sami Mazouz <ilyasmazouz@gmail.com>
2022-07-08 19:24:59 +01:00
Sami Mazouz
d82a73feed fix(approval): unapproved posts visible to all when no visibility scopers are added
Signed-off-by: Sami Mazouz <ilyasmazouz@gmail.com>
2022-07-08 19:16:53 +01:00
Sami Mazouz
ab6cee1a25 test(approval): unapproved content can only be seen by allowed users
Signed-off-by: Sami Mazouz <ilyasmazouz@gmail.com>
2022-07-08 19:16:53 +01:00
Sami Mazouz
2e840dc73d test(sticky): list discussions works as expected with stickies (#3507)
Signed-off-by: Sami Mazouz <ilyasmazouz@gmail.com>
2022-07-08 19:07:03 +01:00
Sami Mazouz
ae9139bd73 chore(subscriptions): enable backend tests
Signed-off-by: Sami Mazouz <ilyasmazouz@gmail.com>
2022-07-07 23:35:29 +01:00
Daniël Klabbers
2e3d6dfa2c chore: upstream changes to dependencies 2022-07-05 21:19:01 +02:00
David Wheatley
7cd28710bc fix: composer title positioning incorrect with custom header height (#3502) 2022-07-04 14:28:44 +01:00
Clark Winkelmann
bc1d6f9e91 fix: assertAdmin sending wrong ability name to gate (#3501) 2022-07-04 14:18:18 +01:00
Sami Mazouz
bf4c543692 fix: restricted sibling tags appearing for unauthorized members on the sidebar (#3419)
* test: user should only be able to see related tags when allowed

* fix: restricted sibling tags appearing for unauthorized members on the sidebar

* fix: apply logic on tags with parents
2022-07-04 12:19:03 +01:00
David Sevilla Martin
709c5566bb fix: overflow notifications group header text with ellipses (#3500)
Fixes #3408
2022-07-04 12:16:59 +01:00
David Wheatley
9a62c32c28 fix: remove return type 2022-07-04 10:52:10 +01:00
85 changed files with 1731 additions and 67 deletions

View File

@@ -6,6 +6,6 @@ jobs:
run:
uses: ./.github/workflows/REUSABLE_backend.yml
with:
enable_backend_testing: false
enable_backend_testing: true
backend_directory: ./extensions/approval

View File

@@ -6,6 +6,6 @@ jobs:
run:
uses: ./.github/workflows/REUSABLE_backend.yml
with:
enable_backend_testing: false
enable_backend_testing: true
backend_directory: ./extensions/likes

View File

@@ -6,6 +6,6 @@ jobs:
run:
uses: ./.github/workflows/REUSABLE_backend.yml
with:
enable_backend_testing: false
enable_backend_testing: true
backend_directory: ./extensions/sticky

View File

@@ -6,6 +6,6 @@ jobs:
run:
uses: ./.github/workflows/REUSABLE_backend.yml
with:
enable_backend_testing: false
enable_backend_testing: true
backend_directory: ./extensions/subscriptions

View File

@@ -6,6 +6,6 @@ jobs:
run:
uses: ./.github/workflows/REUSABLE_backend.yml
with:
enable_backend_testing: false
enable_backend_testing: true
backend_directory: ./extensions/suspend

View File

@@ -1,5 +1,32 @@
# Changelog
## [1.4.0](https://github.com/flarum/framework/compare/v1.3.1...v1.4.0)
### Added
- `created_at` and `updated_at` columns added to several tables (https://github.com/flarum/framework/pull/3435)
- Priorities added to AdminNav links (https://github.com/flarum/framework/pull/3453)
- `app.translator` allows retrieving and setting locale (https://github.com/flarum/framework/pull/3451)
- Extensions can now declare custom settings components for use with `buildSettingComponent` (https://github.com/flarum/framework/pull/3494)
- Implement extensibility on `rel` and `target` attributes on links (https://github.com/flarum/framework/pull/3455)
- New backend tests were added to some of the bundled extensions (https://github.com/flarum/framework/issues/3508)
### Changed
- Split boot script for Flarum in HTML footer into two parts for CSP hashing (https://github.com/flarum/framework/pull/3461)
- Split asset compilation by giving assembling compilers its own method (https://github.com/flarum/framework/pull/3446)
- Increase visibility of Component typescript class for better extensibility (https://github.com/flarum/framework/pull/3437)
### Fixed
- Mentioning an event post breaks the notification dropdown (https://github.com/flarum/framework/pull/3493)
- Suspension modal shows after suspension is over (https://github.com/flarum/framework/pull/3449)
- CLI based installations don't exit with an error code on failure (https://github.com/flarum/framework/pull/3452)
- Tabbing through dropdown controls doesn't make them visible (https://github.com/flarum/framework/pull/3450)
- Requiring zero tags on new discussions forces the user to select tags (https://github.com/flarum/framework/pull/3448)
- Long topic titles in the notification list don't overflow (https://github.com/flarum/framework/pull/3500)
- Subtags of tags the user has access to are visible even if these are not accessible (https://github.com/flarum/framework/pull/3419)
- `assertAdmin` tests access based on wrong gate ability (https://github.com/flarum/framework/pull/3501)
- Increasing the composer header size causes elements to slip underneath (https://github.com/flarum/framework/pull/3502)
- The profile mentions tab errors when sorting by `created_at` (https://github.com/flarum/framework/pull/3506)
## [1.3.1](https://github.com/flarum/framework/compare/v1.3.0...v1.3.1)
### Changed

View File

@@ -29,8 +29,8 @@
}
],
"support": {
"issues": "https://github.com/flarum/core/issues",
"source": "https://github.com/flarum/core",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/framework",
"docs": "https://docs.flarum.org",
"forum": "https://discuss.flarum.org",
"chat": "https://flarum.org/chat"
@@ -86,7 +86,6 @@
"require": {
"ext-json": "*",
"php": ">=7.3",
"axy/sourcemap": "^0.1.4",
"components/font-awesome": "^5.14.0",
"composer/composer": "^2.0",
"dflydev/fig-cookies": "^3.0.0",
@@ -127,6 +126,8 @@
"psr/http-server-middleware": "^1.0",
"pusher/pusher-php-server": "^2.2",
"s9e/text-formatter": "^2.3.6",
"sycho/json-api": "^0.5.0",
"sycho/sourcemap": "^2.0.0",
"symfony/config": "^5.2.2",
"symfony/console": "^5.2.2",
"symfony/event-dispatcher": "^5.2.2",
@@ -134,7 +135,6 @@
"symfony/polyfill-intl-messageformatter": "^1.22.0",
"symfony/translation": "^5.1.5",
"symfony/yaml": "^5.2.2",
"tobscure/json-api": "^0.3.0",
"wikimedia/less.php": "^3.0"
},
"require-dev": {

20
extensions/akismet/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/akismet",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3",
"flarum/core": "^1.4",
"flarum/approval": "^1.2",
"guzzlehttp/guzzle": "^7.4"
},

20
extensions/approval/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/approval",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3",
"flarum/core": "^1.4",
"flarum/flags": "^1.2"
},
"autoload": {
@@ -52,7 +52,7 @@
"prettier": true,
"typescript": false,
"bundlewatch": false,
"backendTesting": false,
"backendTesting": true,
"editorConfig": true,
"styleci": true
}
@@ -65,5 +65,28 @@
}
],
"minimum-stability": "dev",
"prefer-stable": true
"prefer-stable": true,
"autoload-dev": {
"psr-4": {
"Flarum\\Approval\\Tests\\": "tests/"
}
},
"scripts": {
"test": [
"@test:unit",
"@test:integration"
],
"test:unit": "phpunit -c tests/phpunit.unit.xml",
"test:integration": "phpunit -c tests/phpunit.integration.xml",
"test:setup": "@php tests/integration/setup.php"
},
"scripts-descriptions": {
"test": "Runs all tests.",
"test:unit": "Runs all unit tests.",
"test:integration": "Runs all integration tests.",
"test:setup": "Sets up a database for use with integration tests. Execute this only once."
},
"require-dev": {
"flarum/testing": "^1.0.0"
}
}

View File

@@ -9,6 +9,7 @@
namespace Flarum\Approval\Access;
use Closure;
use Flarum\Discussion\Discussion;
use Flarum\User\User;
use Illuminate\Database\Eloquent\Builder;
@@ -39,14 +40,23 @@ class ScopePrivatePostVisibility
});
}
private function discussionWhereCanApprovePosts(User $actor)
/**
* Looks if the actor has permission to approve posts,
* within the discussion which the post is a part of.
*
* For example, the tags extension,
* turns the `approvePosts` ability into per tag basis.
*/
private function discussionWhereCanApprovePosts(User $actor): Closure
{
return function ($query) use ($actor) {
$query->selectRaw('1')
->from('discussions')
->whereColumn('discussions.id', 'posts.discussion_id')
->where(function ($query) use ($actor) {
Discussion::query()->setQuery($query)->whereVisibleTo($actor, 'approvePosts');
$query->whereRaw('1 != 1')->orWhere(function ($query) use ($actor) {
Discussion::query()->setQuery($query)->whereVisibleTo($actor, 'approvePosts');
});
});
};
}

View File

View File

@@ -0,0 +1,75 @@
<?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\Tests\integration;
use Carbon\Carbon;
trait InteractsWithUnapprovedContent
{
protected function prepareUnapprovedDatabaseContent()
{
$this->prepareDatabase([
'users' => [
['id' => 1, 'username' => 'Muralf', 'email' => 'muralf@machine.local', 'is_email_confirmed' => 1],
$this->normalUser(),
['id' => 3, 'username' => 'acme', 'email' => 'acme@machine.local', 'is_email_confirmed' => 1],
['id' => 4, 'username' => 'luceos', 'email' => 'luceos@machine.local', 'is_email_confirmed' => 1],
],
'discussions' => [
['id' => 1, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 1, 'comment_count' => 1, 'is_approved' => 1, 'is_private' => 0],
['id' => 2, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 4, 'first_post_id' => 2, 'comment_count' => 1, 'is_approved' => 0, 'is_private' => 1],
['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' => 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],
],
'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],
['id' => 2, 'discussion_id' => 2, 'user_id' => 4, 'type' => 'comment', 'content' => '<t><p>Text</p></t>', 'is_private' => 0, 'is_approved' => 1, 'number' => 1],
['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' => 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' => 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],
],
'groups' => [
['id' => 4, 'name_singular' => 'Acme', 'name_plural' => 'Acme', 'is_hidden' => 0]
],
'group_user' => [
['user_id' => 3, 'group_id' => 4]
],
'group_permission' => [
['permission' => 'discussion.approvePosts', 'group_id' => 4]
]
]);
}
/**
* 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]];
}
}

View File

@@ -0,0 +1,62 @@
<?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\Tests\integration\api;
use Flarum\Approval\Tests\integration\InteractsWithUnapprovedContent;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Illuminate\Support\Arr;
class ListDiscussionsTest extends TestCase
{
use RetrievesAuthorizedUsers;
use InteractsWithUnapprovedContent;
protected function setUp(): void
{
parent::setUp();
$this->extension('flarum-approval');
$this->prepareUnapprovedDatabaseContent();
}
/**
* @dataProvider unallowedUsers
* @test
*/
public function can_only_see_approved_if_not_allowed_to_approve(?int $authenticatedAs)
{
$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, 4, 5, 7], Arr::pluck($body['data'], 'id'));
}
/**
* @dataProvider allowedUsers
* @test
*/
public function can_see_unapproved_if_allowed_to_approve(int $authenticatedAs)
{
$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'));
}
}

View File

@@ -0,0 +1,74 @@
<?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\Tests\integration\api;
use Flarum\Approval\Tests\integration\InteractsWithUnapprovedContent;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Illuminate\Support\Arr;
class ListPostsTest extends TestCase
{
use RetrievesAuthorizedUsers;
use InteractsWithUnapprovedContent;
protected function setUp(): void
{
parent::setUp();
$this->extension('flarum-approval');
$this->prepareUnapprovedDatabaseContent();
}
/**
* @dataProvider unallowedUsers
* @test
*/
public function can_only_see_approved_if_not_allowed_to_approve(?int $authenticatedAs)
{
$response = $this->send(
$this
->request('GET', '/api/posts', compact('authenticatedAs'))
->withQueryParams([
'filter' => [
'discussion' => 7
]
])
);
$body = json_decode($response->getBody()->getContents(), true);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEqualsCanonicalizing([7, 8, 10], Arr::pluck($body['data'], 'id'));
}
/**
* @dataProvider allowedUsers
* @test
*/
public function can_see_unapproved_if_allowed_to_approve(int $authenticatedAs)
{
$response = $this->send(
$this
->request('GET', '/api/posts', compact('authenticatedAs'))
->withQueryParams([
'filter' => [
'discussion' => 7
]
])
);
$body = json_decode($response->getBody()->getContents(), true);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEqualsCanonicalizing([7, 8, 9, 10, 11], Arr::pluck($body['data'], 'id'));
}
}

View File

@@ -0,0 +1,16 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
use Flarum\Testing\integration\Setup\SetupScript;
require __DIR__.'/../../vendor/autoload.php';
$setup = new SetupScript();
$setup->run();

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="true"
stopOnFailure="false"
>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">../src/</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Flarum Integration Tests">
<directory suffix="Test.php">./integration</directory>
<exclude>./integration/tmp</exclude>
</testsuite>
</testsuites>
</phpunit>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">../src/</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Flarum Unit Tests">
<directory suffix="Test.php">./unit</directory>
</testsuite>
</testsuites>
<listeners>
<listener class="\Mockery\Adapter\Phpunit\TestListener" />
</listeners>
</phpunit>

View File

20
extensions/bbcode/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/bbcode",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3"
"flarum/core": "^1.4"
},
"extra": {
"branch-alias": {

20
extensions/embed/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/embed",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3"
"flarum/core": "^1.4"
},
"autoload": {
"psr-4": {

20
extensions/emoji/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/emoji",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3"
"flarum/core": "^1.4"
},
"extra": {
"branch-alias": {

20
extensions/flags/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/flags",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3"
"flarum/core": "^1.4"
},
"autoload": {
"psr-4": {

20
extensions/lang-english/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

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

20
extensions/likes/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/likes",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3"
"flarum/core": "^1.4"
},
"autoload": {
"psr-4": {
@@ -51,7 +51,7 @@
"prettier": true,
"typescript": false,
"bundlewatch": false,
"backendTesting": false,
"backendTesting": true,
"editorConfig": true,
"styleci": true
}
@@ -64,5 +64,28 @@
}
],
"minimum-stability": "dev",
"prefer-stable": true
"prefer-stable": true,
"autoload-dev": {
"psr-4": {
"Flarum\\Likes\\Tests\\": "tests/"
}
},
"scripts": {
"test": [
"@test:unit",
"@test:integration"
],
"test:unit": "phpunit -c tests/phpunit.unit.xml",
"test:integration": "phpunit -c tests/phpunit.integration.xml",
"test:setup": "@php tests/integration/setup.php"
},
"scripts-descriptions": {
"test": "Runs all tests.",
"test:unit": "Runs all unit tests.",
"test:integration": "Runs all integration tests.",
"test:setup": "Sets up a database for use with integration tests. Execute this only once."
},
"require-dev": {
"flarum/testing": "^1.0.0"
}
}

View File

View File

@@ -0,0 +1,144 @@
<?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;
use Carbon\Carbon;
use Flarum\Post\CommentPost;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Psr\Http\Message\ResponseInterface;
class LikePostTest extends TestCase
{
use RetrievesAuthorizedUsers;
protected function setUp(): void
{
parent::setUp();
$this->extension('flarum-likes');
$this->prepareDatabase([
'users' => [
['id' => 1, 'username' => 'Muralf', 'email' => 'muralf@machine.local', 'is_email_confirmed' => 1],
$this->normalUser(),
['id' => 3, 'username' => 'Acme', 'email' => 'acme@machine.local', 'is_email_confirmed' => 1],
],
'discussions' => [
['id' => 1, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 1, 'first_post_id' => 1, 'comment_count' => 2],
],
'posts' => [
['id' => 1, 'number' => 1, 'discussion_id' => 1, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>something</p></t>'],
['id' => 3, 'number' => 2, 'discussion_id' => 1, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>something</p></t>'],
['id' => 5, 'number' => 3, 'discussion_id' => 1, 'created_at' => Carbon::now(), 'user_id' => 3, 'type' => 'discussionRenamed', 'content' => '<t><p>something</p></t>'],
['id' => 6, 'number' => 4, 'discussion_id' => 1, 'created_at' => Carbon::now(), 'user_id' => 1, 'type' => 'comment', 'content' => '<t><p>something</p></t>'],
],
'groups' => [
['id' => 5, 'name_singular' => 'Acme', 'name_plural' => 'Acme', 'is_hidden' => 0],
['id' => 6, 'name_singular' => 'Acme1', 'name_plural' => 'Acme1', 'is_hidden' => 0]
],
'group_user' => [
['user_id' => 3, 'group_id' => 5]
]
]);
$this->database()->table('group_permission')->where('permission', 'discussion.likePosts')->delete();
$this->database()->table('group_permission')->insert(['permission' => 'discussion.likePosts', 'group_id' => 5]);
}
/**
* @dataProvider allowedUsersToLike
* @test
*/
public function can_like_a_post_if_allowed(int $postId, ?int $authenticatedAs, string $message)
{
$response = $this->sendLikeRequest($postId, $authenticatedAs);
$post = CommentPost::query()->find($postId);
$this->assertEquals(200, $response->getStatusCode());
$this->assertNotNull($post->likes->where('id', $authenticatedAs)->first(), $message);
}
/**
* @dataProvider unallowedUsersToLike
* @test
*/
public function cannot_like_a_post_if_not_allowed(int $postId, ?int $authenticatedAs, string $message)
{
$response = $this->sendLikeRequest($postId, $authenticatedAs);
$post = CommentPost::query()->find($postId);
$this->assertEquals(403, $response->getStatusCode(), $message);
$this->assertNull($post->likes->where('id', $authenticatedAs)->first());
}
/**
* @dataProvider allowedUsersToLike
* @test
*/
public function can_dislike_a_post_if_liked_and_allowed(int $postId, ?int $authenticatedAs, string $message)
{
$this->sendLikeRequest($postId, $authenticatedAs);
$response = $this->sendLikeRequest($postId, $authenticatedAs, false);
$post = CommentPost::query()->find($postId);
$this->assertEquals(200, $response->getStatusCode());
$this->assertNull($post->likes->where('id', $authenticatedAs)->first(), $message);
}
public function allowedUsersToLike(): array
{
return [
[1, 1, 'Admin can like any post'],
[1, 3, 'User with permission can like other posts'],
[6, 3, 'User with permission can like own post']
];
}
public function unallowedUsersToLike(): array
{
return [
[1, null, 'Guest cannot like any post'],
[1, 2, 'User without permission cannot like any post']
];
}
protected function sendLikeRequest(int $postId, ?int $authenticatedAs, bool $liked = true): ResponseInterface
{
if (! isset($authenticatedAs)) {
$initial = $this->send(
$this->request('GET', '/')
);
$token = $initial->getHeaderLine('X-CSRF-Token');
}
$request = $this->request('PATCH', "/api/posts/$postId", [
'authenticatedAs' => $authenticatedAs,
'cookiesFrom' => $initial ?? null,
'json' => [
'data' => [
'attributes' => [
'isLiked' => $liked
]
]
]
]);
if (! isset($authenticatedAs)) {
$request = $request->withHeader('X-CSRF-Token', $token);
}
return $this->send($request);
}
}

View File

@@ -0,0 +1,16 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
use Flarum\Testing\integration\Setup\SetupScript;
require __DIR__.'/../../vendor/autoload.php';
$setup = new SetupScript();
$setup->run();

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="true"
stopOnFailure="false"
>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">../src/</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Flarum Integration Tests">
<directory suffix="Test.php">./integration</directory>
<exclude>./integration/tmp</exclude>
</testsuite>
</testsuites>
</phpunit>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">../src/</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Flarum Unit Tests">
<directory suffix="Test.php">./unit</directory>
</testsuite>
</testsuites>
<listeners>
<listener class="\Mockery\Adapter\Phpunit\TestListener" />
</listeners>
</phpunit>

View File

20
extensions/lock/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/lock",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3"
"flarum/core": "^1.4"
},
"autoload": {
"psr-4": {

20
extensions/markdown/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/markdown",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3"
"flarum/core": "^1.4"
},
"extra": {
"branch-alias": {

20
extensions/mentions/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/mentions",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3"
"flarum/core": "^1.4"
},
"autoload": {
"psr-4": {

View File

@@ -14,7 +14,7 @@ use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Illuminate\Support\Arr;
class ListTest extends TestCase
class ListPostsTest extends TestCase
{
use RetrievesAuthorizedUsers;
@@ -85,4 +85,26 @@ class ListTest extends TestCase
$ids = Arr::pluck($data, 'id');
$this->assertEqualsCanonicalizing(['4'], $ids, 'IDs do not match');
}
/**
* @test
*/
public function mentioned_filter_works_with_sort()
{
$response = $this->send(
$this->request('GET', '/api/posts')
->withQueryParams([
'filter' => ['mentioned' => 1],
'sort' => '-createdAt'
])
);
$data = json_decode($response->getBody()->getContents(), true)['data'];
$this->assertEquals(200, $response->getStatusCode());
// Order-independent comparison
$ids = Arr::pluck($data, 'id');
$this->assertEqualsCanonicalizing(['3', '2'], $ids, 'IDs do not match');
}
}

20
extensions/nicknames/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/nicknames",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3"
"flarum/core": "^1.4"
},
"autoload": {
"psr-4": {

View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

20
extensions/pusher/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/pusher",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3",
"flarum/core": "^1.4",
"pusher/pusher-php-server": "^2.2"
},
"require-dev": {

20
extensions/statistics/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/statistics",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3"
"flarum/core": "^1.4"
},
"autoload": {
"psr-4": {

20
extensions/sticky/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/sticky",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3"
"flarum/core": "^1.4"
},
"autoload": {
"psr-4": {
@@ -51,7 +51,7 @@
"prettier": true,
"typescript": false,
"bundlewatch": false,
"backendTesting": false,
"backendTesting": true,
"editorConfig": true,
"styleci": true
}
@@ -64,5 +64,29 @@
}
],
"minimum-stability": "dev",
"prefer-stable": true
"prefer-stable": true,
"autoload-dev": {
"psr-4": {
"Flarum\\Sticky\\Tests\\": "tests/"
}
},
"scripts": {
"test": [
"@test:unit",
"@test:integration"
],
"test:unit": "phpunit -c tests/phpunit.unit.xml",
"test:integration": "phpunit -c tests/phpunit.integration.xml",
"test:setup": "@php tests/integration/setup.php"
},
"scripts-descriptions": {
"test": "Runs all tests.",
"test:unit": "Runs all unit tests.",
"test:integration": "Runs all integration tests.",
"test:setup": "Sets up a database for use with integration tests. Execute this only once."
},
"require-dev": {
"flarum/tags": "*@dev",
"flarum/testing": "^1.0.0"
}
}

View File

View File

@@ -0,0 +1,120 @@
<?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\Sticky\tests\integration\api;
use Carbon\Carbon;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Illuminate\Support\Arr;
class ListDiscussionsTest extends TestCase
{
use RetrievesAuthorizedUsers;
protected function setUp(): void
{
parent::setUp();
$this->extension('flarum-tags', 'flarum-sticky');
$this->prepareDatabase([
'users' => [
['id' => 1, 'username' => 'Muralf', 'email' => 'muralf@machine.local', 'is_email_confirmed' => 1],
$this->normalUser(),
['id' => 3, 'username' => 'Muralf_', 'email' => 'muralf_@machine.local', 'is_email_confirmed' => 1],
],
'discussions' => [
['id' => 1, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 1, 'first_post_id' => 1, 'comment_count' => 1, 'is_sticky' => true, 'last_post_number' => 1],
['id' => 2, 'title' => __CLASS__, 'created_at' => Carbon::now()->addMinutes(2), 'last_posted_at' => Carbon::now()->addMinutes(5), 'user_id' => 1, 'first_post_id' => 1, 'comment_count' => 1, 'is_sticky' => false, 'last_post_number' => 1],
['id' => 3, 'title' => __CLASS__, 'created_at' => Carbon::now()->addMinutes(3), 'last_posted_at' => Carbon::now()->addMinute(), 'user_id' => 1, 'first_post_id' => 1, 'comment_count' => 1, 'is_sticky' => true, 'last_post_number' => 1],
['id' => 4, 'title' => __CLASS__, 'created_at' => Carbon::now()->addMinutes(4), 'last_posted_at' => Carbon::now()->addMinutes(2), 'user_id' => 1, 'first_post_id' => 1, 'comment_count' => 1, 'is_sticky' => false, 'last_post_number' => 1],
],
'discussion_user' => [
['discussion_id' => 1, 'user_id' => 3, 'last_read_post_number' => 1],
['discussion_id' => 3, 'user_id' => 3, 'last_read_post_number' => 1],
],
'tags' => [
['id' => 1, 'slug' => 'general', 'position' => 0, 'parent_id' => null]
],
'discussion_tag' => [
['discussion_id' => 1, 'tag_id' => 1],
['discussion_id' => 2, 'tag_id' => 1],
['discussion_id' => 3, 'tag_id' => 1],
['discussion_id' => 4, 'tag_id' => 1],
]
]);
}
/** @test */
public function list_discussions_shows_sticky_first_as_guest()
{
$response = $this->send(
$this->request('GET', '/api/discussions')
);
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($response->getBody()->getContents(), true);
$this->assertEquals([3, 1, 2, 4], Arr::pluck($data['data'], 'id'));
}
/** @test */
public function list_discussions_shows_sticky_unread_first_as_user()
{
$response = $this->send(
$this->request('GET', '/api/discussions', [
'authenticatedAs' => 2
])
);
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($response->getBody()->getContents(), true);
$this->assertEquals([3, 1, 2, 4], Arr::pluck($data['data'], 'id'));
}
/** @test */
public function list_discussions_shows_normal_order_when_all_read_as_user()
{
$response = $this->send(
$this->request('GET', '/api/discussions', [
'authenticatedAs' => 3
])
);
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($response->getBody()->getContents(), true);
$this->assertEquals([2, 4, 3, 1], Arr::pluck($data['data'], 'id'));
}
/** @test */
public function list_discussions_shows_stick_first_on_a_tag()
{
$response = $this->send(
$this->request('GET', '/api/discussions', [
'authenticatedAs' => 3
])->withQueryParams([
'filter' => [
'tag' => 'general'
]
])
);
$this->assertEquals(200, $response->getStatusCode());
$data = json_decode($response->getBody()->getContents(), true);
$this->assertEquals([3, 1, 2, 4], Arr::pluck($data['data'], 'id'));
}
}

View File

@@ -0,0 +1,16 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
use Flarum\Testing\integration\Setup\SetupScript;
require __DIR__.'/../../vendor/autoload.php';
$setup = new SetupScript();
$setup->run();

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="true"
stopOnFailure="false"
>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">../src/</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Flarum Integration Tests">
<directory suffix="Test.php">./integration</directory>
<exclude>./integration/tmp</exclude>
</testsuite>
</testsuites>
</phpunit>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">../src/</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Flarum Unit Tests">
<directory suffix="Test.php">./unit</directory>
</testsuite>
</testsuites>
<listeners>
<listener class="\Mockery\Adapter\Phpunit\TestListener" />
</listeners>
</phpunit>

View File

20
extensions/subscriptions/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/subscriptions",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3"
"flarum/core": "^1.4"
},
"autoload": {
"psr-4": {

20
extensions/suspend/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/suspend",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3"
"flarum/core": "^1.4"
},
"autoload": {
"psr-4": {
@@ -51,7 +51,7 @@
"prettier": true,
"typescript": false,
"bundlewatch": false,
"backendTesting": false,
"backendTesting": true,
"editorConfig": true,
"styleci": true
}
@@ -64,5 +64,28 @@
}
],
"minimum-stability": "dev",
"prefer-stable": true
"prefer-stable": true,
"autoload-dev": {
"psr-4": {
"Flarum\\Suspend\\Tests\\": "tests/"
}
},
"scripts": {
"test": [
"@test:unit",
"@test:integration"
],
"test:unit": "phpunit -c tests/phpunit.unit.xml",
"test:integration": "phpunit -c tests/phpunit.integration.xml",
"test:setup": "@php tests/integration/setup.php"
},
"scripts-descriptions": {
"test": "Runs all tests.",
"test:unit": "Runs all unit tests.",
"test:integration": "Runs all integration tests.",
"test:setup": "Sets up a database for use with integration tests. Execute this only once."
},
"require-dev": {
"flarum/testing": "^1.0.0"
}
}

View File

View File

@@ -0,0 +1,86 @@
<?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\Suspend\Tests\integration\api;
use Carbon\Carbon;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
class UseForumTest extends TestCase
{
use RetrievesAuthorizedUsers;
protected function setUp(): void
{
parent::setUp();
$this->extension('flarum-suspend');
$this->prepareDatabase([
'users' => [
['id' => 1, 'username' => 'Muralf', 'email' => 'muralf@machine.local', 'is_email_confirmed' => 1],
['id' => 2, 'username' => 'SuspendedDonny', 'email' => 'acme@machine.local', 'is_email_confirmed' => 1, 'suspended_until' => Carbon::now()->addDay(), 'suspend_reason' => 'acme', 'suspend_message' => 'acme'],
],
'discussions' => [
['id' => 1, 'title' => __CLASS__, 'created_at' => Carbon::now(), 'last_posted_at' => Carbon::now(), 'user_id' => 1, 'first_post_id' => 1, 'comment_count' => 1],
],
'posts' => [
['id' => 1, 'number' => 1, 'created_at' => Carbon::now(), 'user_id' => 1, 'discussion_id' => 1, 'content' => '<t><p>Hello, world!</p></t>'],
]
]);
}
/** @test */
public function suspended_user_cannot_create_discussions()
{
$response = $this->send(
$this->request('POST', '/api/discussions', [
'authenticatedAs' => 2,
'json' => [
'data' => [
'attributes' => [
'title' => 'Test post',
'content' => '<t><p>Hello, world!</p></t>'
],
],
],
])
);
$this->assertEquals(403, $response->getStatusCode());
}
/** @test */
public function suspended_user_cannot_reply_to_discussions()
{
$response = $this->send(
$this->request('POST', '/api/posts', [
'authenticatedAs' => 2,
'json' => [
'data' => [
'attributes' => [
'content' => '<t><p>Hello, world!</p></t>'
],
'relationships' => [
'discussion' => [
'data' => [
'type' => 'discussions',
'id' => 1,
],
],
],
],
],
])
);
$this->assertEquals(403, $response->getStatusCode());
}
}

View File

@@ -0,0 +1,75 @@
<?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\Suspend\Tests\integration\api\users;
use Carbon\Carbon;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Illuminate\Support\Arr;
class ListUsersTest extends TestCase
{
use RetrievesAuthorizedUsers;
protected function setUp(): void
{
parent::setUp();
$this->extension('flarum-suspend');
$this->prepareDatabase([
'users' => [
['id' => 1, 'username' => 'Muralf', 'email' => 'muralf@machine.local', 'is_email_confirmed' => 1],
['id' => 2, 'username' => 'SuspendedDonny1', 'email' => 'acme1@machine.local', 'is_email_confirmed' => 1, 'suspended_until' => Carbon::now()->addDay(), 'suspend_reason' => 'acme', 'suspend_message' => 'acme'],
['id' => 3, 'username' => 'SuspendedDonny2', 'email' => 'acme2@machine.local', 'is_email_confirmed' => 1, 'suspended_until' => Carbon::now()->addDay(), 'suspend_reason' => 'acme', 'suspend_message' => 'acme'],
['id' => 4, 'username' => 'SuspendedDonny3', 'email' => 'acme3@machine.local', 'is_email_confirmed' => 1, 'suspended_until' => Carbon::now()->subDay(), 'suspend_reason' => 'acme', 'suspend_message' => 'acme'],
['id' => 5, 'username' => 'SuspendedDonny4', 'email' => 'acme4@machine.local', 'is_email_confirmed' => 1, 'suspended_until' => Carbon::now()->addDay(), 'suspend_reason' => 'acme', 'suspend_message' => 'acme'],
['id' => 6, 'username' => 'Acme', 'email' => 'acme5@machine.local', 'is_email_confirmed' => 1],
]
]);
}
public function can_view_default_users_list()
{
$response = $this->send(
$this->request('GET', '/api/users', [
'authenticatedAs' => 1,
])->withQueryParams([
'filter' => [
'suspended' => true,
],
])
);
$body = json_decode($response->getBody()->getContents(), true);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEqualsCanonicalizing([1, 2, 3, 4, 5, 6], Arr::pluck($body['data'], 'id'));
}
/** @test */
public function can_filter_users_by_suspension()
{
$response = $this->send(
$this->request('GET', '/api/users', [
'authenticatedAs' => 1,
])->withQueryParams([
'filter' => [
'suspended' => true,
],
])
);
$body = json_decode($response->getBody()->getContents(), true);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEqualsCanonicalizing([2, 3, 5], Arr::pluck($body['data'], 'id'));
}
}

View File

@@ -0,0 +1,104 @@
<?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\Suspend\Tests\integration\api\users;
use Carbon\Carbon;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Psr\Http\Message\ResponseInterface;
class SuspendUserTest extends TestCase
{
use RetrievesAuthorizedUsers;
protected function setUp(): void
{
parent::setUp();
$this->extension('flarum-suspend');
$this->prepareDatabase([
'users' => [
['id' => 1, 'username' => 'Muralf', 'email' => 'muralf@machine.local', 'is_email_confirmed' => 1],
$this->normalUser(),
['id' => 3, 'username' => 'acme', 'email' => 'acme@machine.local', 'is_email_confirmed' => 1],
],
'groups' => [
['id' => 5, 'name_singular' => 'Acme', 'name_plural' => 'Acme', 'is_hidden' => 0]
],
'group_user' => [
['user_id' => 3, 'group_id' => 5]
],
'group_permission' => [
['permission' => 'user.suspend', 'group_id' => 5]
]
]);
}
/**
* @dataProvider allowedToSuspendUser
* @test
*/
public function can_suspend_user_if_allowed(?int $authenticatedAs, int $targetUserId, string $message)
{
$response = $this->sendSuspensionRequest($authenticatedAs, $targetUserId);
$this->assertEquals(200, $response->getStatusCode());
}
/**
* @dataProvider unallowedToSuspendUser
* @test
*/
public function cannot_suspend_user_if_not_allowed(?int $authenticatedAs, int $targetUserId, string $message)
{
$response = $this->sendSuspensionRequest($authenticatedAs, $targetUserId);
$this->assertEquals(403, $response->getStatusCode());
}
public function allowedToSuspendUser(): array
{
return [
[1, 2, 'Admin can suspend any user'],
[1, 3, 'Admin can suspend any user'],
[3, 2, 'User with permission can suspend any user'],
];
}
public function unallowedToSuspendUser(): array
{
return [
[1, 1, 'Admin cannot suspend self'],
[2, 2, 'User without permission cannot suspend self'],
[2, 3, 'User without permission cannot suspend other user'],
[3, 3, 'User with permission cannot suspend self'],
[3, 1, 'User with permission cannot suspend admin'],
];
}
protected function sendSuspensionRequest(?int $authenticatedAs, int $targetUserId): ResponseInterface
{
return $this->send(
$this->request('PATCH', "/api/users/$targetUserId", [
'authenticatedAs' => $authenticatedAs,
'json' => [
'data' => [
'attributes' => [
'suspendedUntil' => Carbon::now()->addDay(),
'suspendReason' => 'Suspended for acme reasons.',
'suspendMessage' => 'You have been suspended.',
]
]
]
])
);
}
}

View File

@@ -0,0 +1,16 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
use Flarum\Testing\integration\Setup\SetupScript;
require __DIR__.'/../../vendor/autoload.php';
$setup = new SetupScript();
$setup->run();

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="true"
stopOnFailure="false"
>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">../src/</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Flarum Integration Tests">
<directory suffix="Test.php">./integration</directory>
<exclude>./integration/tmp</exclude>
</testsuite>
</testsuites>
</phpunit>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">../src/</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Flarum Unit Tests">
<directory suffix="Test.php">./unit</directory>
</testsuite>
</testsuites>
<listeners>
<listener class="\Mockery\Adapter\Phpunit\TestListener" />
</listeners>
</phpunit>

View File

20
extensions/tags/.gitattributes vendored Normal file
View File

@@ -0,0 +1,20 @@
**/.gitattributes export-ignore
**/.gitignore export-ignore
**/.gitmodules export-ignore
**/.github export-ignore
**/.travis export-ignore
**/.travis.yml export-ignore
**/.editorconfig export-ignore
**/.styleci.yml export-ignore
**/phpunit.xml export-ignore
**/tests export-ignore
**/js/dist/**/* -diff
**/js/dist/**/* linguist-generated
**/js/dist-typings/**/* -diff
**/js/dist-typings/**/* linguist-generated
**/js/yarn.lock -diff
**/js/package-lock.json -diff
* text=auto eol=lf

View File

@@ -7,7 +7,7 @@
],
"license": "MIT",
"support": {
"issues": "https://github.com/flarum/core/issues",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/tags",
"forum": "https://discuss.flarum.org"
},
@@ -19,7 +19,7 @@
}
],
"require": {
"flarum/core": "^1.3"
"flarum/core": "^1.4"
},
"autoload": {
"psr-4": {

View File

@@ -49,11 +49,26 @@ class ShowTagController extends AbstractShowController
$slug = Arr::get($request->getQueryParams(), 'slug');
$actor = RequestUtil::getActor($request);
$include = $this->extractInclude($request);
$setParentOnChildren = false;
return $this->tags
if (in_array('parent.children.parent', $include, true)) {
$setParentOnChildren = true;
$include[] = 'parent.children';
$include = array_unique(array_diff($include, ['parent.children.parent']));
}
$tag = $this->tags
->with($include, $actor)
->whereVisibleTo($actor)
->where('slug', $slug)
->firstOrFail();
if ($setParentOnChildren && $tag->parent) {
foreach ($tag->parent->children as $child) {
$child->parent = $tag->parent;
}
}
return $tag;
}
}

View File

@@ -14,7 +14,7 @@ use Illuminate\Database\Eloquent\Builder;
class TagRepository
{
private const TAG_RELATIONS = ['children', 'parent'];
private const TAG_RELATIONS = ['children', 'parent', 'parent.children'];
/**
* Get a new query builder for the tags table.

View File

@@ -83,15 +83,16 @@ class ListTest extends TestCase
}
/**
* @dataProvider listTagsIncludes
* @test
*/
public function user_sees_where_allowed_with_included_tags()
public function user_sees_where_allowed_with_included_tags(string $include, array $expectedIncludes)
{
$response = $this->send(
$this->request('GET', '/api/tags', [
'authenticatedAs' => 2,
])->withQueryParams([
'include' => 'children'
'include' => $include
])
);
@@ -106,7 +107,7 @@ class ListTest extends TestCase
// 6, 7, 8 aren't included because child access shouldnt work unless parent
// access is also given.
$this->assertEquals(['1', '2', '3', '4', '9', '10', '11'], Arr::pluck($data, 'id'));
$this->assertEquals(['3', '4'], Arr::pluck($included, 'id'));
$this->assertEquals($expectedIncludes, Arr::pluck($included, 'id'));
}
/**
@@ -125,4 +126,12 @@ class ListTest extends TestCase
$ids = Arr::pluck($data, 'id');
$this->assertEquals(['1', '2', '3', '4', '9', '10'], $ids);
}
public function listTagsIncludes(): array
{
return [
['children', ['3', '4']],
['parent', ['2']],
];
}
}

View File

@@ -0,0 +1,75 @@
<?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\Tags\Tests\integration\api\tags;
use Flarum\Group\Group;
use Flarum\Tags\Tests\integration\RetrievesRepresentativeTags;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Illuminate\Support\Arr;
class ShowTest extends TestCase
{
use RetrievesAuthorizedUsers;
use RetrievesRepresentativeTags;
/**
* @inheritDoc
*/
protected function setUp(): void
{
parent::setUp();
$this->extension('flarum-tags');
$this->prepareDatabase([
'tags' => $this->tags(),
'users' => [
$this->normalUser(),
],
'group_permission' => [
['group_id' => Group::MEMBER_ID, 'permission' => 'tag8.viewForum'],
['group_id' => Group::MEMBER_ID, 'permission' => 'tag11.viewForum']
]
]);
}
/**
* @dataProvider showTagIncludes
* @test
*/
public function user_sees_tag_relations_where_allowed(string $include, array $expectedIncludes)
{
$response = $this->send(
$this->request('GET', '/api/tags/primary-2-child-2', [
'authenticatedAs' => 2,
])->withQueryParams([
'include' => $include
])
);
$this->assertEquals(200, $response->getStatusCode());
$responseBody = json_decode($response->getBody()->getContents(), true);
$included = $responseBody['included'] ?? [];
$this->assertEqualsCanonicalizing($expectedIncludes, Arr::pluck($included, 'id'));
}
public function showTagIncludes(): array
{
return [
['children', []],
['parent', ['2']],
['parent.children', ['3', '2']],
['parent.children.parent', ['3', '2']],
];
}
}

View File

@@ -29,8 +29,8 @@
}
],
"support": {
"issues": "https://github.com/flarum/core/issues",
"source": "https://github.com/flarum/core",
"issues": "https://github.com/flarum/framework/issues",
"source": "https://github.com/flarum/flarum-core",
"docs": "https://docs.flarum.org",
"forum": "https://discuss.flarum.org",
"chat": "https://flarum.org/chat"

View File

@@ -190,6 +190,7 @@
}
.normal &:first-child {
height: var(--header-height-phone);
margin: calc(~"0px - var(--header-height-phone)") 50px 0;
text-align: center;
position: relative;
@@ -198,6 +199,9 @@
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: flex;
align-items: center;
justify-content: center;
h3 {
color: var(--header-control-color);

View File

@@ -68,14 +68,17 @@
color: var(--heading-color) !important;
padding: 8px 16px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: flex;
align-items: center;
// Prevent outline overflowing parent
.add-keyboard-focus-ring-offset(-1px);
&, span {
overflow: hidden;
text-overflow: ellipsis;
}
}
&-badges {

View File

@@ -113,6 +113,20 @@ class ListPostsController extends AbstractListController
return $results;
}
/**
* @link https://github.com/flarum/framework/pull/3506
*/
protected function extractSort(ServerRequestInterface $request)
{
$sort = [];
foreach ((parent::extractSort($request) ?: []) as $field => $direction) {
$sort["posts.$field"] = $direction;
}
return $sort;
}
/**
* {@inheritdoc}
*/

View File

@@ -21,7 +21,7 @@ class Application
*
* @var string
*/
const VERSION = '1.3.1';
const VERSION = '1.4.0';
/**
* The IoC container for the Flarum application.

View File

@@ -53,7 +53,7 @@ class Assets
return $this;
}
public function __invoke(Document $document, Request $request): void
public function __invoke(Document $document, Request $request)
{
$locale = $request->getAttribute('locale');

View File

@@ -650,7 +650,7 @@ class User extends AbstractModel
*/
public function assertAdmin()
{
$this->assertCan($this, 'administrate');
$this->assertCan('administrate');
}
/**