mirror of
https://github.com/flarum/framework.git
synced 2025-02-21 16:24:27 +08:00
Update APIs, clean up
This commit is contained in:
parent
ce0f77d858
commit
a351c2ef3c
@ -9,20 +9,26 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Flarum\Core\Application;
|
||||
use Flarum\Tags\Access;
|
||||
use Flarum\Tags\Listener;
|
||||
use Flarum\Tags\Tag;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
return function (Application $app) {
|
||||
Flarum\Tags\Tag::setValidator($app->make('validator'));
|
||||
return function (Dispatcher $events) {
|
||||
$events->subscribe(Listener\AddClientAssets::class);
|
||||
$events->subscribe(Listener\AddDiscussionTagsRelationship::class);
|
||||
$events->subscribe(Listener\AddForumTagsRelationship::class);
|
||||
$events->subscribe(Listener\AddTagsApi::class);
|
||||
$events->subscribe(Listener\CreatePostWhenTagsAreChanged::class);
|
||||
$events->subscribe(Listener\FilterDiscussionListByTags::class);
|
||||
$events->subscribe(Listener\SaveTagsToDatabase::class);
|
||||
$events->subscribe(Listener\UpdateTagMetadata::class);
|
||||
|
||||
$events = $app->make('events');
|
||||
$events->subscribe(Access\DiscussionPolicy::class);
|
||||
$events->subscribe(Access\TagPolicy::class);
|
||||
$events->subscribe(Access\FlagPolicy::class);
|
||||
|
||||
$events->subscribe('Flarum\Tags\Listeners\AddClientAssets');
|
||||
$events->subscribe('Flarum\Tags\Listeners\AddModelRelationship');
|
||||
$events->subscribe('Flarum\Tags\Listeners\ConfigureDiscussionPermissions');
|
||||
$events->subscribe('Flarum\Tags\Listeners\ConfigureTagPermissions');
|
||||
$events->subscribe('Flarum\Tags\Listeners\AddApiAttributes');
|
||||
$events->subscribe('Flarum\Tags\Listeners\PersistData');
|
||||
$events->subscribe('Flarum\Tags\Listeners\LogDiscussionTagged');
|
||||
$events->subscribe('Flarum\Tags\Listeners\UpdateTagMetadata');
|
||||
$events->subscribe('Flarum\Tags\Listeners\AddTagGambit');
|
||||
Tag::saving(function ($model) {
|
||||
$this->app->make('Flarum\Tags\TagValidator')->assertValid($model);
|
||||
});
|
||||
};
|
||||
|
1336
extensions/tags/js/admin/dist/extension.js
vendored
1336
extensions/tags/js/admin/dist/extension.js
vendored
File diff suppressed because one or more lines are too long
1356
extensions/tags/js/forum/dist/extension.js
vendored
1356
extensions/tags/js/forum/dist/extension.js
vendored
File diff suppressed because one or more lines are too long
@ -1,5 +1,5 @@
|
||||
import EventPost from 'flarum/components/EventPost';
|
||||
import punctuate from 'flarum/helpers/punctuate';
|
||||
import punctuateSeries from 'flarum/helpers/punctuateSeries';
|
||||
import tagsLabel from 'flarum/tags/helpers/tagsLabel';
|
||||
|
||||
export default class DiscussionTaggedPost extends EventPost {
|
||||
@ -41,7 +41,7 @@ export default class DiscussionTaggedPost extends EventPost {
|
||||
}
|
||||
|
||||
return {
|
||||
action: punctuate(actions),
|
||||
action: punctuateSeries(actions),
|
||||
count: added.length + removed.length
|
||||
};
|
||||
}
|
||||
|
@ -10,16 +10,11 @@
|
||||
|
||||
namespace Flarum\Tags\Migrations;
|
||||
|
||||
use Flarum\Database\AbstractMigration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Flarum\Migrations\Migration;
|
||||
|
||||
class CreateDiscussionsTagsTable extends Migration
|
||||
class CreateDiscussionsTagsTable extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$this->schema->create('discussions_tags', function (Blueprint $table) {
|
||||
@ -29,11 +24,6 @@ class CreateDiscussionsTagsTable extends Migration
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
$this->schema->drop('discussions_tags');
|
||||
|
@ -10,17 +10,12 @@
|
||||
|
||||
namespace Flarum\Tags\Migrations;
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Flarum\Migrations\Migration;
|
||||
use Flarum\Database\AbstractMigration;
|
||||
use Flarum\Tags\Tag;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
class CreateTagsTable extends Migration
|
||||
class CreateTagsTable extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$this->schema->create('tags', function (Blueprint $table) {
|
||||
@ -53,11 +48,6 @@ class CreateTagsTable extends Migration
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
$this->schema->drop('tags');
|
||||
|
@ -10,16 +10,11 @@
|
||||
|
||||
namespace Flarum\Tags\Migrations;
|
||||
|
||||
use Flarum\Database\AbstractMigration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Flarum\Migrations\Migration;
|
||||
|
||||
class CreateUsersTagsTable extends Migration
|
||||
class CreateUsersTagsTable extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$this->schema->create('users_tags', function (Blueprint $table) {
|
||||
@ -31,11 +26,6 @@ class CreateUsersTagsTable extends Migration
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
$this->schema->drop('users_tags');
|
||||
|
@ -10,33 +10,23 @@
|
||||
|
||||
namespace Flarum\Tags\Migrations;
|
||||
|
||||
use Flarum\Migrations\Migration;
|
||||
use Flarum\Database\AbstractMigration;
|
||||
|
||||
class SetDefaultSettings extends Migration
|
||||
class SetDefaultSettings extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$this->settings->set('tags.max_primary_tags', '1');
|
||||
$this->settings->set('tags.min_primary_tags', '1');
|
||||
$this->settings->set('tags.max_secondary_tags', '3');
|
||||
$this->settings->set('tags.min_secondary_tags', '0');
|
||||
$this->settings->set('flarum-tags.max_primary_tags', '1');
|
||||
$this->settings->set('flarum-tags.min_primary_tags', '1');
|
||||
$this->settings->set('flarum-tags.max_secondary_tags', '3');
|
||||
$this->settings->set('flarum-tags.min_secondary_tags', '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
$this->settings->delete('tags.max_primary_tags');
|
||||
$this->settings->delete('tags.max_secondary_tags');
|
||||
$this->settings->delete('tags.min_primary_tags');
|
||||
$this->settings->delete('tags.min_secondary_tags');
|
||||
$this->settings->delete('flarum-tags.max_primary_tags');
|
||||
$this->settings->delete('flarum-tags.max_secondary_tags');
|
||||
$this->settings->delete('flarum-tags.min_primary_tags');
|
||||
$this->settings->delete('flarum-tags.min_secondary_tags');
|
||||
}
|
||||
}
|
||||
|
106
extensions/tags/src/Access/DiscussionPolicy.php
Executable file
106
extensions/tags/src/Access/DiscussionPolicy.php
Executable file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Access;
|
||||
|
||||
use Flarum\Core\Access\AbstractPolicy;
|
||||
use Flarum\Core\Discussion;
|
||||
use Flarum\Core\User;
|
||||
use Flarum\Event\ScopeHiddenDiscussionVisibility;
|
||||
use Flarum\Tags\Tag;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
|
||||
class DiscussionPolicy extends AbstractPolicy
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $model = Discussion::class;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function subscribe(Dispatcher $events)
|
||||
{
|
||||
parent::subscribe($events);
|
||||
|
||||
$events->listen(ScopeHiddenDiscussionVisibility::class, [$this, 'scopeHiddenDiscussionVisibility']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $actor
|
||||
* @param string $ability
|
||||
* @param Discussion $discussion
|
||||
* @return bool
|
||||
*/
|
||||
public function before(User $actor, $ability, Discussion $discussion)
|
||||
{
|
||||
// Wrap all discussion permission checks with some logic pertaining to
|
||||
// the discussion's tags. If the discussion has a tag that has been
|
||||
// restricted, and the user has this permission for that tag, then they
|
||||
// are allowed. If the discussion only has tags that have been
|
||||
// restricted, then the user *must* have permission for at least one of
|
||||
// them.
|
||||
$tags = $discussion->tags;
|
||||
|
||||
if (count($tags)) {
|
||||
$restricted = true;
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
if ($tag->is_restricted) {
|
||||
if ($actor->hasPermission('tag' . $tag->id . '.discussion.' . $ability)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
$restricted = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($restricted) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $actor
|
||||
* @param Builder $query
|
||||
*/
|
||||
public function find(User $actor, Builder $query)
|
||||
{
|
||||
// Hide discussions which have tags that the user is not allowed to see.
|
||||
$query->whereNotExists(function ($query) use ($actor) {
|
||||
return $query->select(new Expression(1))
|
||||
->from('discussions_tags')
|
||||
->whereIn('tag_id', Tag::getIdsWhereCannot($actor, 'view'))
|
||||
->where('discussions.id', new Expression('discussion_id'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ScopeHiddenDiscussionVisibility $event
|
||||
*/
|
||||
public function scopeHiddenDiscussionVisibility(ScopeHiddenDiscussionVisibility $event)
|
||||
{
|
||||
// By default, discussions are not visible to the public if they are
|
||||
// hidden or contain zero comments - unless the actor has a certain
|
||||
// permission. Since we grant permissions per-tag, we will make
|
||||
// discussions visible in the tags for which the user has that
|
||||
// permission.
|
||||
$event->query->orWhereExists(function ($query) use ($event) {
|
||||
return $query->select(new Expression(1))
|
||||
->from('discussions_tags')
|
||||
->whereIn('tag_id', Tag::getIdsWhereCan($event->actor, $event->permission))
|
||||
->where('discussions.id', new Expression('discussion_id'));
|
||||
});
|
||||
}
|
||||
}
|
43
extensions/tags/src/Access/FlagPolicy.php
Executable file
43
extensions/tags/src/Access/FlagPolicy.php
Executable file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Access;
|
||||
|
||||
use Flarum\Core\Access\AbstractPolicy;
|
||||
use Flarum\Core\User;
|
||||
use Flarum\Flags\Flag;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
|
||||
class FlagPolicy extends AbstractPolicy
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $model = Flag::class;
|
||||
|
||||
/**
|
||||
* @param User $actor
|
||||
* @param Builder $query
|
||||
*/
|
||||
public function find(User $actor, Builder $query)
|
||||
{
|
||||
$query
|
||||
->select('flags.*')
|
||||
->leftJoin('posts', 'posts.id', '=', 'flags.post_id')
|
||||
->leftJoin('discussions', 'discussions.id', '=', 'posts.discussion_id')
|
||||
->whereNotExists(function ($query) use ($actor) {
|
||||
return $query->select(new Expression(1))
|
||||
->from('discussions_tags')
|
||||
->whereIn('tag_id', Tag::getIdsWhereCannot($actor, 'discussion.viewFlags'))
|
||||
->where('discussions.id', new Expression('discussion_id'));
|
||||
});
|
||||
}
|
||||
}
|
47
extensions/tags/src/Access/TagPolicy.php
Executable file
47
extensions/tags/src/Access/TagPolicy.php
Executable file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Access;
|
||||
|
||||
use Flarum\Core\Access\AbstractPolicy;
|
||||
use Flarum\Core\User;
|
||||
use Flarum\Tags\Tag;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class TagPolicy extends AbstractPolicy
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $model = Tag::class;
|
||||
|
||||
/**
|
||||
* @param User $actor
|
||||
* @param Builder $query
|
||||
*/
|
||||
public function find(User $actor, Builder $query)
|
||||
{
|
||||
$query->whereNotIn('id', Tag::getIdsWhereCannot($actor, 'view'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $actor
|
||||
* @param Tag $tag
|
||||
* @return bool|null
|
||||
*/
|
||||
public function startDiscussion(User $actor, Tag $tag)
|
||||
{
|
||||
if (! $tag->is_restricted
|
||||
|| $actor->hasPermission('tag' . $tag->id . '.startDiscussion')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -8,26 +8,27 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Api;
|
||||
namespace Flarum\Tags\Api\Controller;
|
||||
|
||||
use Flarum\Tags\Commands\EditTag;
|
||||
use Flarum\Api\Actions\SerializeResourceAction;
|
||||
use Flarum\Api\JsonApiRequest;
|
||||
use Flarum\Api\Controller\AbstractCreateController;
|
||||
use Flarum\Tags\Api\Serializer\TagSerializer;
|
||||
use Flarum\Tags\Command\CreateTag;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Tobscure\JsonApi\Document;
|
||||
|
||||
class UpdateAction extends SerializeResourceAction
|
||||
class CreateTagController extends AbstractCreateController
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $serializer = TagSerializer::class;
|
||||
|
||||
/**
|
||||
* @var Dispatcher
|
||||
*/
|
||||
protected $bus;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $serializer = 'Flarum\Tags\Api\TagSerializer';
|
||||
|
||||
/**
|
||||
* @param Dispatcher $bus
|
||||
*/
|
||||
@ -37,14 +38,12 @@ class UpdateAction extends SerializeResourceAction
|
||||
}
|
||||
|
||||
/**
|
||||
* @param JsonApiRequest $request
|
||||
* @param Document $document
|
||||
* @return \Flarum\Core\Tags\Tag
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function data(JsonApiRequest $request, Document $document)
|
||||
protected function data(ServerRequestInterface $request, Document $document)
|
||||
{
|
||||
return $this->bus->dispatch(
|
||||
new EditTag($request->get('id'), $request->actor, $request->get('data'))
|
||||
new CreateTag($request->getAttribute('actor'), array_get($request->getParsedBody(), 'data'))
|
||||
);
|
||||
}
|
||||
}
|
@ -8,14 +8,14 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Api;
|
||||
namespace Flarum\Tags\Api\Controller;
|
||||
|
||||
use Flarum\Tags\Commands\DeleteTag;
|
||||
use Flarum\Api\Actions\DeleteAction as BaseDeleteAction;
|
||||
use Flarum\Api\Request;
|
||||
use Flarum\Api\Controller\AbstractDeleteController;
|
||||
use Flarum\Tags\Command\DeleteTag;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class DeleteAction extends BaseDeleteAction
|
||||
class DeleteTagController extends AbstractDeleteController
|
||||
{
|
||||
/**
|
||||
* @var Dispatcher
|
||||
@ -31,14 +31,12 @@ class DeleteAction extends BaseDeleteAction
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a tag.
|
||||
*
|
||||
* @param Request $request
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function delete(Request $request)
|
||||
protected function delete(ServerRequestInterface $request)
|
||||
{
|
||||
$this->bus->dispatch(
|
||||
new DeleteTag($request->get('id'), $request->actor)
|
||||
new DeleteTag(array_get($request->getQueryParams(), 'id'), $request->getAttribute('actor'))
|
||||
);
|
||||
}
|
||||
}
|
@ -8,23 +8,26 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Api;
|
||||
namespace Flarum\Tags\Api\Controller;
|
||||
|
||||
use Flarum\Api\Actions\Action;
|
||||
use Flarum\Api\Request;
|
||||
use Zend\Diactoros\Response\EmptyResponse;
|
||||
use Flarum\Core\Access\AssertPermissionTrait;
|
||||
use Flarum\Http\Controller\ControllerInterface;
|
||||
use Flarum\Tags\Tag;
|
||||
use Flarum\Core\Exceptions\PermissionDeniedException;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Zend\Diactoros\Response\EmptyResponse;
|
||||
|
||||
class OrderAction implements Action
|
||||
class OrderTagsController implements ControllerInterface
|
||||
{
|
||||
public function handle(Request $request)
|
||||
{
|
||||
if (! $request->actor->isAdmin()) {
|
||||
throw new PermissionDeniedException;
|
||||
}
|
||||
use AssertPermissionTrait;
|
||||
|
||||
$order = $request->get('order');
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request)
|
||||
{
|
||||
$this->assertAdmin($request->getAttribute('actor'));
|
||||
|
||||
$order = array_get($request->getParsedBody(), 'order');
|
||||
|
||||
Tag::query()->update([
|
||||
'position' => null,
|
53
extensions/tags/src/Api/Controller/UpdateTagController.php
Normal file
53
extensions/tags/src/Api/Controller/UpdateTagController.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Api\Controller;
|
||||
|
||||
use Flarum\Api\Controller\AbstractResourceController;
|
||||
use Flarum\Tags\Api\Serializer\TagSerializer;
|
||||
use Flarum\Tags\Command\EditTag;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Tobscure\JsonApi\Document;
|
||||
|
||||
class UpdateTagController extends AbstractResourceController
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $serializer = TagSerializer::class;
|
||||
|
||||
/**
|
||||
* @var Dispatcher
|
||||
*/
|
||||
protected $bus;
|
||||
|
||||
/**
|
||||
* @param Dispatcher $bus
|
||||
*/
|
||||
public function __construct(Dispatcher $bus)
|
||||
{
|
||||
$this->bus = $bus;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function data(ServerRequestInterface $request, Document $document)
|
||||
{
|
||||
$id = array_get($request->getQueryParams(), 'id');
|
||||
$actor = $request->getAttribute('actor');
|
||||
$data = array_get($request->getParsedBody(), 'data');
|
||||
|
||||
return $this->bus->dispatch(
|
||||
new EditTag($id, $actor, $data)
|
||||
);
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Api;
|
||||
|
||||
use Flarum\Tags\Commands\CreateTag;
|
||||
use Flarum\Api\Actions\CreateAction as BaseCreateAction;
|
||||
use Flarum\Api\JsonApiRequest;
|
||||
use Illuminate\Contracts\Bus\Dispatcher;
|
||||
|
||||
class CreateAction extends BaseCreateAction
|
||||
{
|
||||
/**
|
||||
* @var Dispatcher
|
||||
*/
|
||||
protected $bus;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $serializer = 'Flarum\Tags\Api\TagSerializer';
|
||||
|
||||
/**
|
||||
* @param Dispatcher $bus
|
||||
*/
|
||||
public function __construct(Dispatcher $bus)
|
||||
{
|
||||
$this->bus = $bus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a tag according to input from the API request.
|
||||
*
|
||||
* @param JsonApiRequest $request
|
||||
* @return \Flarum\Core\Tags\Tag
|
||||
*/
|
||||
protected function create(JsonApiRequest $request)
|
||||
{
|
||||
return $this->bus->dispatch(
|
||||
new CreateTag($request->actor, $request->get('data'))
|
||||
);
|
||||
}
|
||||
}
|
@ -8,14 +8,21 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Api;
|
||||
namespace Flarum\Tags\Api\Serializer;
|
||||
|
||||
use Flarum\Api\Serializers\Serializer;
|
||||
use Flarum\Api\Serializer\AbstractSerializer;
|
||||
use Flarum\Api\Serializer\DiscussionSerializer;
|
||||
|
||||
class TagSerializer extends Serializer
|
||||
class TagSerializer extends AbstractSerializer
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $type = 'tags';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getDefaultAttributes($tag)
|
||||
{
|
||||
$attributes = [
|
||||
@ -31,8 +38,8 @@ class TagSerializer extends Serializer
|
||||
'defaultSort' => $tag->default_sort,
|
||||
'isChild' => (bool) $tag->parent_id,
|
||||
'isHidden' => (bool) $tag->is_hidden,
|
||||
'lastTime' => $tag->last_time ? $tag->last_time->toRFC3339String() : null,
|
||||
'canStartDiscussion' => $tag->can($this->actor, 'startDiscussion')
|
||||
'lastTime' => $this->formatDate($tag->last_time),
|
||||
'canStartDiscussion' => $this->actor->can('startDiscussion', $tag)
|
||||
];
|
||||
|
||||
if ($this->actor->isAdmin()) {
|
||||
@ -42,13 +49,19 @@ class TagSerializer extends Serializer
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Flarum\Api\Relationship\HasOneBuilder
|
||||
*/
|
||||
protected function parent()
|
||||
{
|
||||
return $this->hasOne('Flarum\Tags\Api\TagSerializer');
|
||||
return $this->hasOne(TagSerializer::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Flarum\Api\Relationship\HasOneBuilder
|
||||
*/
|
||||
protected function lastDiscussion()
|
||||
{
|
||||
return $this->hasOne('Flarum\Api\Serializers\DiscussionSerializer');
|
||||
return $this->hasOne(DiscussionSerializer::class);
|
||||
}
|
||||
}
|
@ -8,9 +8,9 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Commands;
|
||||
namespace Flarum\Tags\Command;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
use Flarum\Core\User;
|
||||
|
||||
class CreateTag
|
||||
{
|
@ -8,26 +8,14 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Commands;
|
||||
namespace Flarum\Tags\Command;
|
||||
|
||||
use Flarum\Core\Access\AssertPermissionTrait;
|
||||
use Flarum\Tags\Tag;
|
||||
use Flarum\Core\Forum;
|
||||
use Flarum\Events\TagWillBeSaved;
|
||||
|
||||
class CreateTagHandler
|
||||
{
|
||||
/**
|
||||
* @var Forum
|
||||
*/
|
||||
protected $forum;
|
||||
|
||||
/**
|
||||
* @param Forum $forum
|
||||
*/
|
||||
public function __construct(Forum $forum)
|
||||
{
|
||||
$this->forum = $forum;
|
||||
}
|
||||
use AssertPermissionTrait;
|
||||
|
||||
/**
|
||||
* @param CreateTag $command
|
||||
@ -38,7 +26,7 @@ class CreateTagHandler
|
||||
$actor = $command->actor;
|
||||
$data = $command->data;
|
||||
|
||||
$this->forum->assertCan($actor, 'createTag');
|
||||
$this->assertCan($actor, 'createTag');
|
||||
|
||||
$tag = Tag::build(
|
||||
array_get($data, 'attributes.name'),
|
@ -8,10 +8,9 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Commands;
|
||||
namespace Flarum\Tags\Command;
|
||||
|
||||
use Flarum\Tags\Tag;
|
||||
use Flarum\Core\Users\User;
|
||||
use Flarum\Core\User;
|
||||
|
||||
class DeleteTag
|
||||
{
|
@ -8,13 +8,15 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Commands;
|
||||
namespace Flarum\Tags\Command;
|
||||
|
||||
use Flarum\Tags\Tag;
|
||||
use Flarum\Core\Access\AssertPermissionTrait;
|
||||
use Flarum\Tags\TagRepository;
|
||||
|
||||
class DeleteTagHandler
|
||||
{
|
||||
use AssertPermissionTrait;
|
||||
|
||||
/**
|
||||
* @var TagRepository
|
||||
*/
|
||||
@ -30,8 +32,8 @@ class DeleteTagHandler
|
||||
|
||||
/**
|
||||
* @param DeleteTag $command
|
||||
* @return Tag
|
||||
* @throws \Flarum\Core\Exceptions\PermissionDeniedException
|
||||
* @return \Flarum\Tags\Tag
|
||||
* @throws \Flarum\Core\Exception\PermissionDeniedException
|
||||
*/
|
||||
public function handle(DeleteTag $command)
|
||||
{
|
||||
@ -39,7 +41,7 @@ class DeleteTagHandler
|
||||
|
||||
$tag = $this->tags->findOrFail($command->tagId, $actor);
|
||||
|
||||
$tag->assertCan($actor, 'delete');
|
||||
$this->assertCan($actor, 'delete', $tag);
|
||||
|
||||
$tag->delete();
|
||||
|
@ -8,10 +8,9 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Commands;
|
||||
namespace Flarum\Tags\Command;
|
||||
|
||||
use Flarum\Core\Tags\Tag;
|
||||
use Flarum\Core\Users\User;
|
||||
use Flarum\Core\User;
|
||||
|
||||
class EditTag
|
||||
{
|
@ -8,13 +8,15 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Commands;
|
||||
namespace Flarum\Tags\Command;
|
||||
|
||||
use Flarum\Tags\Tag;
|
||||
use Flarum\Core\Access\AssertPermissionTrait;
|
||||
use Flarum\Tags\TagRepository;
|
||||
|
||||
class EditTagHandler
|
||||
{
|
||||
use AssertPermissionTrait;
|
||||
|
||||
/**
|
||||
* @var TagRepository
|
||||
*/
|
||||
@ -30,8 +32,8 @@ class EditTagHandler
|
||||
|
||||
/**
|
||||
* @param EditTag $command
|
||||
* @return Tag
|
||||
* @throws \Flarum\Core\Exceptions\PermissionDeniedException
|
||||
* @return \Flarum\Tags\Tag
|
||||
* @throws \Flarum\Core\Exception\PermissionDeniedException
|
||||
*/
|
||||
public function handle(EditTag $command)
|
||||
{
|
||||
@ -40,7 +42,7 @@ class EditTagHandler
|
||||
|
||||
$tag = $this->tags->findOrFail($command->tagId, $actor);
|
||||
|
||||
$tag->assertCan($actor, 'edit');
|
||||
$this->assertCan($actor, 'edit', $tag);
|
||||
|
||||
$attributes = array_get($data, 'attributes', []);
|
||||
|
@ -8,10 +8,10 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Events;
|
||||
namespace Flarum\Tags\Event;
|
||||
|
||||
use Flarum\Core\Discussions\Discussion;
|
||||
use Flarum\Core\Users\User;
|
||||
use Flarum\Core\Discussion;
|
||||
use Flarum\Core\User;
|
||||
|
||||
class DiscussionWasTagged
|
||||
{
|
@ -8,31 +8,37 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Gambits;
|
||||
namespace Flarum\Tags\Gambit;
|
||||
|
||||
use Flarum\Core\Search\AbstractRegexGambit;
|
||||
use Flarum\Core\Search\AbstractSearch;
|
||||
use Flarum\Tags\TagRepository;
|
||||
use Flarum\Core\Search\Search;
|
||||
use Flarum\Core\Search\RegexGambit;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
|
||||
class TagGambit extends RegexGambit
|
||||
class TagGambit extends AbstractRegexGambit
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $pattern = 'tag:(.+)';
|
||||
|
||||
/**
|
||||
* @var \Flarum\Tags\TagRepository
|
||||
* @var TagRepository
|
||||
*/
|
||||
protected $tags;
|
||||
|
||||
/**
|
||||
* @param \Flarum\Tags\TagRepository $tags
|
||||
* @param TagRepository $tags
|
||||
*/
|
||||
public function __construct(TagRepository $tags)
|
||||
{
|
||||
$this->tags = $tags;
|
||||
}
|
||||
|
||||
protected function conditions(Search $search, array $matches, $negate)
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function conditions(AbstractSearch $search, array $matches, $negate)
|
||||
{
|
||||
$slugs = explode(',', trim($matches[1], '"'));
|
||||
|
||||
@ -41,7 +47,7 @@ class TagGambit extends RegexGambit
|
||||
foreach ($slugs as $slug) {
|
||||
if ($slug === 'untagged') {
|
||||
$query->orWhereNotExists(function ($query) {
|
||||
$query->select(app('flarum.db')->raw(1))
|
||||
$query->select(new Expression(1))
|
||||
->from('discussions_tags')
|
||||
->where('discussions.id', new Expression('discussion_id'));
|
||||
});
|
||||
@ -49,7 +55,7 @@ class TagGambit extends RegexGambit
|
||||
$id = $this->tags->getIdForSlug($slug);
|
||||
|
||||
$query->orWhereExists(function ($query) use ($id) {
|
||||
$query->select(app('flarum.db')->raw(1))
|
||||
$query->select(new Expression(1))
|
||||
->from('discussions_tags')
|
||||
->where('discussions.id', new Expression('discussion_id'))
|
||||
->where('tag_id', $id);
|
@ -8,32 +8,35 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Listeners;
|
||||
namespace Flarum\Tags\Listener;
|
||||
|
||||
use Flarum\Events\RegisterLocales;
|
||||
use Flarum\Events\BuildClientView;
|
||||
use Flarum\Events\RegisterForumRoutes;
|
||||
use Flarum\Event\ConfigureClientView;
|
||||
use Flarum\Event\ConfigureForumRoutes;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
class AddClientAssets
|
||||
{
|
||||
/**
|
||||
* @param Dispatcher $events
|
||||
*/
|
||||
public function subscribe(Dispatcher $events)
|
||||
{
|
||||
$events->listen(BuildClientView::class, [$this, 'addAssets']);
|
||||
$events->listen(RegisterForumRoutes::class, [$this, 'addRoutes']);
|
||||
$events->listen(ConfigureClientView::class, [$this, 'addAssets']);
|
||||
$events->listen(ConfigureForumRoutes::class, [$this, 'addRoutes']);
|
||||
}
|
||||
|
||||
public function addAssets(BuildClientView $event)
|
||||
/**
|
||||
* @param ConfigureClientView $event
|
||||
*/
|
||||
public function addAssets(ConfigureClientView $event)
|
||||
{
|
||||
if ($event->isForum()) {
|
||||
$event->addAssets([
|
||||
__DIR__.'/../../js/forum/dist/extension.js',
|
||||
__DIR__.'/../../less/forum/extension.less'
|
||||
]);
|
||||
|
||||
$event->addBootstrapper('flarum/tags/main');
|
||||
|
||||
$event->addTranslations(['flarum-tags.forum']);
|
||||
$event->addTranslations('flarum-tags.forum');
|
||||
}
|
||||
|
||||
if ($event->isAdmin()) {
|
||||
@ -41,14 +44,16 @@ class AddClientAssets
|
||||
__DIR__.'/../../js/admin/dist/extension.js',
|
||||
__DIR__.'/../../less/admin/extension.less'
|
||||
]);
|
||||
|
||||
$event->addBootstrapper('flarum/tags/main');
|
||||
}
|
||||
}
|
||||
|
||||
public function addRoutes(RegisterForumRoutes $event)
|
||||
/**
|
||||
* @param ConfigureForumRoutes $event
|
||||
*/
|
||||
public function addRoutes(ConfigureForumRoutes $event)
|
||||
{
|
||||
$event->get('/t/{slug}', 'tags.forum.tag');
|
||||
$event->get('/tags', 'tags.forum.tags');
|
||||
$event->get('/t/{slug}', 'tag');
|
||||
$event->get('/tags', 'tags');
|
||||
}
|
||||
}
|
83
extensions/tags/src/Listener/AddDiscussionTagsRelationship.php
Executable file
83
extensions/tags/src/Listener/AddDiscussionTagsRelationship.php
Executable file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Listener;
|
||||
|
||||
use Flarum\Api\Controller;
|
||||
use Flarum\Api\Serializer\DiscussionSerializer;
|
||||
use Flarum\Core\Discussion;
|
||||
use Flarum\Event\ConfigureApiController;
|
||||
use Flarum\Event\GetApiRelationship;
|
||||
use Flarum\Event\GetModelRelationship;
|
||||
use Flarum\Event\PrepareApiAttributes;
|
||||
use Flarum\Tags\Tag;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
class AddDiscussionTagsRelationship
|
||||
{
|
||||
/**
|
||||
* @param Dispatcher $events
|
||||
*/
|
||||
public function subscribe(Dispatcher $events)
|
||||
{
|
||||
$events->listen(GetModelRelationship::class, [$this, 'getModelRelationship']);
|
||||
$events->listen(GetApiRelationship::class, [$this, 'getApiRelationship']);
|
||||
$events->listen(ConfigureApiController::class, [$this, 'includeTagsRelationship']);
|
||||
$events->listen(PrepareApiAttributes::class, [$this, 'prepareApiAttributes']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GetModelRelationship $event
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany|null
|
||||
*/
|
||||
public function getModelRelationship(GetModelRelationship $event)
|
||||
{
|
||||
if ($event->isRelationship(Discussion::class, 'tags')) {
|
||||
return $event->model->belongsToMany(Tag::class, 'discussions_tags', null, null, 'tags');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GetApiRelationship $event
|
||||
* @return \Flarum\Api\Relationship\HasManyBuilder|null
|
||||
*/
|
||||
public function getApiRelationship(GetApiRelationship $event)
|
||||
{
|
||||
if ($event->isRelationship(DiscussionSerializer::class, 'tags')) {
|
||||
return $event->serializer->hasMany('Flarum\Tags\Api\Serializer\TagSerializer', 'tags');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConfigureApiController $event
|
||||
*/
|
||||
public function includeTagsRelationship(ConfigureApiController $event)
|
||||
{
|
||||
if ($event->isController(Controller\ListDiscussionsController::class)
|
||||
|| $event->isController(Controller\ShowDiscussionController::class)
|
||||
|| $event->isController(Controller\CreateDiscussionController::class)) {
|
||||
$event->addInclude('tags');
|
||||
}
|
||||
|
||||
if ($event->isController(Controller\CreateDiscussionController::class)) {
|
||||
$event->addInclude('tags.lastDiscussion');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PrepareApiAttributes $event
|
||||
*/
|
||||
public function prepareApiAttributes(PrepareApiAttributes $event)
|
||||
{
|
||||
if ($event->isSerializer(DiscussionSerializer::class)) {
|
||||
$event->attributes['canTag'] = $event->actor->can('tag', $event->model);
|
||||
}
|
||||
}
|
||||
}
|
96
extensions/tags/src/Listener/AddForumTagsRelationship.php
Executable file
96
extensions/tags/src/Listener/AddForumTagsRelationship.php
Executable file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Listener;
|
||||
|
||||
use Flarum\Api\Controller\ShowForumController;
|
||||
use Flarum\Api\Serializer\ForumSerializer;
|
||||
use Flarum\Event\ConfigureApiController;
|
||||
use Flarum\Event\GetApiRelationship;
|
||||
use Flarum\Event\PrepareApiAttributes;
|
||||
use Flarum\Event\PrepareApiData;
|
||||
use Flarum\Settings\SettingsRepository;
|
||||
use Flarum\Tags\Tag;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
class AddForumTagsRelationship
|
||||
{
|
||||
/**
|
||||
* @var SettingsRepository
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* @param SettingsRepository $settings
|
||||
*/
|
||||
public function __construct(SettingsRepository $settings)
|
||||
{
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Dispatcher $events
|
||||
*/
|
||||
public function subscribe(Dispatcher $events)
|
||||
{
|
||||
$events->listen(GetApiRelationship::class, [$this, 'getApiRelationship']);
|
||||
$events->listen(PrepareApiData::class, [$this, 'loadTagsRelationship']);
|
||||
$events->listen(ConfigureApiController::class, [$this, 'includeTagsRelationship']);
|
||||
$events->listen(PrepareApiAttributes::class, [$this, 'prepareApiAttributes']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GetApiRelationship $event
|
||||
* @return \Flarum\Api\Relationship\HasManyBuilder|null
|
||||
*/
|
||||
public function getApiRelationship(GetApiRelationship $event)
|
||||
{
|
||||
if ($event->isRelationship(ForumSerializer::class, 'tags')) {
|
||||
return $event->serializer->hasMany('Flarum\Tags\Api\Serializer\TagSerializer', 'tags');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PrepareApiData $event
|
||||
*/
|
||||
public function loadTagsRelationship(PrepareApiData $event)
|
||||
{
|
||||
// Expose the complete tag list to clients by adding it as a
|
||||
// relationship to the /api/forum endpoint. Since the Forum model
|
||||
// doesn't actually have a tags relationship, we will manually load and
|
||||
// assign the tags data to it using an event listener.
|
||||
if ($event->isController(ShowForumController::class)) {
|
||||
$event->data['tags'] = Tag::whereVisibleTo($event->actor)->with('lastDiscussion')->get();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConfigureApiController $event
|
||||
*/
|
||||
public function includeTagsRelationship(ConfigureApiController $event)
|
||||
{
|
||||
if ($event->isController(ShowForumController::class)) {
|
||||
$event->addInclude(['tags', 'tags.lastDiscussion', 'tags.parent']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PrepareApiAttributes $event
|
||||
*/
|
||||
public function prepareApiAttributes(PrepareApiAttributes $event)
|
||||
{
|
||||
if ($event->isSerializer(ForumSerializer::class)) {
|
||||
$event->attributes['minPrimaryTags'] = $this->settings->get('flarum-tags.min_primary_tags');
|
||||
$event->attributes['maxPrimaryTags'] = $this->settings->get('flarum-tags.max_primary_tags');
|
||||
$event->attributes['minSecondaryTags'] = $this->settings->get('flarum-tags.min_secondary_tags');
|
||||
$event->attributes['maxSecondaryTags'] = $this->settings->get('flarum-tags.max_secondary_tags');
|
||||
}
|
||||
}
|
||||
}
|
31
extensions/tags/src/Listener/AddTagsApi.php
Executable file
31
extensions/tags/src/Listener/AddTagsApi.php
Executable file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Listener;
|
||||
|
||||
use Flarum\Tags\Api\Controller;
|
||||
use Flarum\Event\ConfigureApiRoutes;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
class AddTagsApi
|
||||
{
|
||||
public function subscribe(Dispatcher $events)
|
||||
{
|
||||
$events->listen(ConfigureApiRoutes::class, [$this, 'configureApiRoutes']);
|
||||
}
|
||||
|
||||
public function configureApiRoutes(ConfigureApiRoutes $event)
|
||||
{
|
||||
$event->post('/tags', 'tags.create', Controller\CreateTagController::class);
|
||||
$event->post('/tags/order', 'tags.order', Controller\OrderTagsController::class);
|
||||
$event->patch('/tags/{id}', 'tags.update', Controller\UpdateTagController::class);
|
||||
$event->delete('/tags/{id}', 'tags.delete', Controller\DeleteTagController::class);
|
||||
}
|
||||
}
|
@ -8,26 +8,35 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Listeners;
|
||||
namespace Flarum\Tags\Listener;
|
||||
|
||||
use Flarum\Events\RegisterPostTypes;
|
||||
use Flarum\Tags\Posts\DiscussionTaggedPost;
|
||||
use Flarum\Tags\Events\DiscussionWasTagged;
|
||||
use Flarum\Event\ConfigurePostTypes;
|
||||
use Flarum\Tags\Event\DiscussionWasTagged;
|
||||
use Flarum\Tags\Post\DiscussionTaggedPost;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
class LogDiscussionTagged
|
||||
class CreatePostWhenTagsAreChanged
|
||||
{
|
||||
/**
|
||||
* @param Dispatcher $events
|
||||
*/
|
||||
public function subscribe(Dispatcher $events)
|
||||
{
|
||||
$events->listen(RegisterPostTypes::class, [$this, 'registerPostType']);
|
||||
$events->listen(ConfigurePostTypes::class, [$this, 'addPostType']);
|
||||
$events->listen(DiscussionWasTagged::class, [$this, 'whenDiscussionWasTagged']);
|
||||
}
|
||||
|
||||
public function registerPostType(RegisterPostTypes $event)
|
||||
/**
|
||||
* @param ConfigurePostTypes $event
|
||||
*/
|
||||
public function addPostType(ConfigurePostTypes $event)
|
||||
{
|
||||
$event->register(DiscussionTaggedPost::class);
|
||||
$event->add(DiscussionTaggedPost::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DiscussionWasTagged $event
|
||||
*/
|
||||
public function whenDiscussionWasTagged(DiscussionWasTagged $event)
|
||||
{
|
||||
$post = DiscussionTaggedPost::reply(
|
@ -8,29 +8,38 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Listeners;
|
||||
namespace Flarum\Tags\Listener;
|
||||
|
||||
use Flarum\Events\RegisterDiscussionGambits;
|
||||
use Flarum\Events\DiscussionSearchWillBePerformed;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Flarum\Tags\Gambits\TagGambit;
|
||||
use Flarum\Event\ConfigureDiscussionGambits;
|
||||
use Flarum\Event\DiscussionSearchWillBePerformed;
|
||||
use Flarum\Tags\Gambit\TagGambit;
|
||||
use Flarum\Tags\Tag;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
|
||||
class AddTagGambit
|
||||
class FilterDiscussionListByTags
|
||||
{
|
||||
/**
|
||||
* @param Dispatcher $events
|
||||
*/
|
||||
public function subscribe(Dispatcher $events)
|
||||
{
|
||||
$events->listen(RegisterDiscussionGambits::class, [$this, 'registerTagGambit']);
|
||||
$events->listen(DiscussionSearchWillBePerformed::class, [$this, 'hideTags']);
|
||||
$events->listen(ConfigureDiscussionGambits::class, [$this, 'addTagGambit']);
|
||||
$events->listen(DiscussionSearchWillBePerformed::class, [$this, 'hideTagsFromDiscussionList']);
|
||||
}
|
||||
|
||||
public function registerTagGambit(RegisterDiscussionGambits $event)
|
||||
/**
|
||||
* @param ConfigureDiscussionGambits $event
|
||||
*/
|
||||
public function addTagGambit(ConfigureDiscussionGambits $event)
|
||||
{
|
||||
$event->gambits->add('Flarum\Tags\Gambits\TagGambit');
|
||||
$event->gambits->add(TagGambit::class);
|
||||
}
|
||||
|
||||
public function hideTags(DiscussionSearchWillBePerformed $event)
|
||||
/**
|
||||
* @param DiscussionSearchWillBePerformed $event
|
||||
*/
|
||||
public function hideTagsFromDiscussionList(DiscussionSearchWillBePerformed $event)
|
||||
{
|
||||
$query = $event->search->getQuery();
|
||||
|
||||
@ -41,7 +50,7 @@ class AddTagGambit
|
||||
}
|
||||
|
||||
$query->whereNotExists(function ($query) {
|
||||
return $query->select(app('flarum.db')->raw(1))
|
||||
return $query->select(new Expression(1))
|
||||
->from('discussions_tags')
|
||||
->whereIn('tag_id', Tag::where('is_hidden', 1)->lists('id'))
|
||||
->where('discussions.id', new Expression('discussion_id'));
|
@ -8,32 +8,47 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Listeners;
|
||||
namespace Flarum\Tags\Listener;
|
||||
|
||||
use Flarum\Core\Exception\PermissionDeniedException;
|
||||
use Flarum\Core\Exception\ValidationException;
|
||||
use Flarum\Event\DiscussionWillBeSaved;
|
||||
use Flarum\Settings\SettingsRepository;
|
||||
use Flarum\Tags\Event\DiscussionWasTagged;
|
||||
use Flarum\Tags\Tag;
|
||||
use Flarum\Tags\Events\DiscussionWasTagged;
|
||||
use Flarum\Events\DiscussionWillBeSaved;
|
||||
use Flarum\Core\Discussions\Discussion;
|
||||
use Flarum\Core\Exceptions\PermissionDeniedException;
|
||||
use Flarum\Core\Settings\SettingsRepository;
|
||||
use Flarum\Tags\TagCountException;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
class PersistData
|
||||
class SaveTagsToDatabase
|
||||
{
|
||||
/**
|
||||
* @var SettingsRepository
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* @param SettingsRepository $settings
|
||||
*/
|
||||
public function __construct(SettingsRepository $settings)
|
||||
{
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
public function subscribe($events)
|
||||
/**
|
||||
* @param Dispatcher $events
|
||||
*/
|
||||
public function subscribe(Dispatcher $events)
|
||||
{
|
||||
$events->listen(DiscussionWillBeSaved::class, [$this, 'whenDiscussionWillBeSaved']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DiscussionWillBeSaved $event
|
||||
* @throws PermissionDeniedException
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function whenDiscussionWillBeSaved(DiscussionWillBeSaved $event)
|
||||
{
|
||||
// TODO: clean up, prevent discussion from being created without tags
|
||||
if (isset($event->data['relationships']['tags']['data'])) {
|
||||
$discussion = $event->discussion;
|
||||
$actor = $event->actor;
|
||||
@ -49,7 +64,7 @@ class PersistData
|
||||
$secondaryCount = 0;
|
||||
|
||||
foreach ($newTags as $tag) {
|
||||
if (! $tag->can($actor, 'startDiscussion')) {
|
||||
if ($actor->cannot('startDiscussion', $tag)) {
|
||||
throw new PermissionDeniedException;
|
||||
}
|
||||
|
||||
@ -63,8 +78,6 @@ class PersistData
|
||||
$this->validatePrimaryTagCount($primaryCount);
|
||||
$this->validateSecondaryTagCount($secondaryCount);
|
||||
|
||||
$oldTags = [];
|
||||
|
||||
if ($discussion->exists) {
|
||||
$oldTags = $discussion->tags()->get();
|
||||
$oldTagIds = $oldTags->lists('id');
|
||||
@ -73,32 +86,46 @@ class PersistData
|
||||
return;
|
||||
}
|
||||
|
||||
$discussion->raise(new DiscussionWasTagged($discussion, $actor, $oldTags->all()));
|
||||
$discussion->raise(
|
||||
new DiscussionWasTagged($discussion, $actor, $oldTags->all())
|
||||
);
|
||||
}
|
||||
|
||||
Discussion::saved(function ($discussion) use ($newTagIds) {
|
||||
$discussion->afterSave(function ($discussion) use ($newTagIds) {
|
||||
$discussion->tags()->sync($newTagIds);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $count
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function validatePrimaryTagCount($count)
|
||||
{
|
||||
$min = $this->settings->get('tags.min_primary_tags');
|
||||
$max = $this->settings->get('tags.max_primary_tags');
|
||||
$min = $this->settings->get('flarum-tags.min_primary_tags');
|
||||
$max = $this->settings->get('flarum-tags.max_primary_tags');
|
||||
|
||||
if ($count < $min || $count > $max) {
|
||||
throw new TagCountException(['tags' => sprintf('Discussion must have between %d and %d primary tags.', $min, $max)]);
|
||||
throw new ValidationException([
|
||||
'tags' => sprintf('Discussion must have between %d and %d primary tags.', $min, $max)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $count
|
||||
* @throws ValidationException
|
||||
*/
|
||||
protected function validateSecondaryTagCount($count)
|
||||
{
|
||||
$min = $this->settings->get('tags.min_secondary_tags');
|
||||
$max = $this->settings->get('tags.max_secondary_tags');
|
||||
$min = $this->settings->get('flarum-tags.min_secondary_tags');
|
||||
$max = $this->settings->get('flarum-tags.max_secondary_tags');
|
||||
|
||||
if ($count < $min || $count > $max) {
|
||||
throw new TagCountException(['tags' => sprintf('Discussion must have between %d and %d secondary tags.', $min, $max)]);
|
||||
throw new ValidationException([
|
||||
'tags' => sprintf('Discussion must have between %d and %d secondary tags.', $min, $max)
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
@ -8,22 +8,25 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Listeners;
|
||||
namespace Flarum\Tags\Listener;
|
||||
|
||||
use Flarum\Core\Post;
|
||||
use Flarum\Event\DiscussionWasDeleted;
|
||||
use Flarum\Event\DiscussionWasStarted;
|
||||
use Flarum\Event\PostWasDeleted;
|
||||
use Flarum\Event\PostWasHidden;
|
||||
use Flarum\Event\PostWasPosted;
|
||||
use Flarum\Event\PostWasRestored;
|
||||
use Flarum\Tags\Event\DiscussionWasTagged;
|
||||
use Flarum\Tags\Tag;
|
||||
use Flarum\Tags\Events\DiscussionWasTagged;
|
||||
use Flarum\Events\DiscussionWasStarted;
|
||||
use Flarum\Events\DiscussionWasDeleted;
|
||||
use Flarum\Core\Discussions\Discussion;
|
||||
use Flarum\Core\Posts\Post;
|
||||
use Flarum\Events\PostWasPosted;
|
||||
use Flarum\Events\PostWasDeleted;
|
||||
use Flarum\Events\PostWasHidden;
|
||||
use Flarum\Events\PostWasRestored;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
class UpdateTagMetadata
|
||||
{
|
||||
public function subscribe($events)
|
||||
/**
|
||||
* @param Dispatcher $events
|
||||
*/
|
||||
public function subscribe(Dispatcher $events)
|
||||
{
|
||||
$events->listen(DiscussionWasStarted::class, [$this, 'whenDiscussionWasStarted']);
|
||||
$events->listen(DiscussionWasTagged::class, [$this, 'whenDiscussionWasTagged']);
|
||||
@ -35,20 +38,28 @@ class UpdateTagMetadata
|
||||
$events->listen(PostWasRestored::class, [$this, 'whenPostWasRestored']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DiscussionWasStarted $event
|
||||
*/
|
||||
public function whenDiscussionWasStarted(DiscussionWasStarted $event)
|
||||
{
|
||||
$this->updateTags($event->discussion, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DiscussionWasTagged $event
|
||||
*/
|
||||
public function whenDiscussionWasTagged(DiscussionWasTagged $event)
|
||||
{
|
||||
$oldTags = Tag::whereIn('id', array_pluck($event->oldTags, 'id'));
|
||||
|
||||
$this->updateTags($event->discussion, -1, $oldTags);
|
||||
|
||||
$this->updateTags($event->discussion, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DiscussionWasDeleted $event
|
||||
*/
|
||||
public function whenDiscussionWasDeleted(DiscussionWasDeleted $event)
|
||||
{
|
||||
$this->updateTags($event->discussion, -1);
|
||||
@ -56,26 +67,43 @@ class UpdateTagMetadata
|
||||
$event->discussion->tags()->detach();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostWasPosted $event
|
||||
*/
|
||||
public function whenPostWasPosted(PostWasPosted $event)
|
||||
{
|
||||
$this->updateTags($event->post->discussion);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostWasDeleted $event
|
||||
*/
|
||||
public function whenPostWasDeleted(PostWasDeleted $event)
|
||||
{
|
||||
$this->updateTags($event->post->discussion);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostWasHidden $event
|
||||
*/
|
||||
public function whenPostWasHidden(PostWasHidden $event)
|
||||
{
|
||||
$this->updateTags($event->post->discussion);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostWasRestored $event
|
||||
*/
|
||||
public function whenPostWasRestored(PostWasRestored $event)
|
||||
{
|
||||
$this->updateTags($event->post->discussion);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Flarum\Core\Discussion $discussion
|
||||
* @param int $delta
|
||||
* @param Tag[]|null $tags
|
||||
*/
|
||||
protected function updateTags($discussion, $delta = 0, $tags = null)
|
||||
{
|
||||
if (! $tags) {
|
@ -1,106 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Listeners;
|
||||
|
||||
use Flarum\Events\ApiRelationship;
|
||||
use Flarum\Events\WillSerializeData;
|
||||
use Flarum\Events\BuildApiAction;
|
||||
use Flarum\Events\ApiAttributes;
|
||||
use Flarum\Events\RegisterApiRoutes;
|
||||
use Flarum\Api\Actions\Forum;
|
||||
use Flarum\Api\Actions\Discussions;
|
||||
use Flarum\Api\Serializers\ForumSerializer;
|
||||
use Flarum\Api\Serializers\DiscussionSerializer;
|
||||
use Flarum\Tags\Tag;
|
||||
|
||||
class AddApiAttributes
|
||||
{
|
||||
public function subscribe($events)
|
||||
{
|
||||
$events->listen(ApiRelationship::class, [$this, 'addTagsRelationship']);
|
||||
$events->listen(WillSerializeData::class, [$this, 'loadTagsRelationship']);
|
||||
$events->listen(BuildApiAction::class, [$this, 'includeTagsRelationship']);
|
||||
$events->listen(ApiAttributes::class, [$this, 'addAttributes']);
|
||||
$events->listen(RegisterApiRoutes::class, [$this, 'addRoutes']);
|
||||
}
|
||||
|
||||
public function addTagsRelationship(ApiRelationship $event)
|
||||
{
|
||||
if ($event->serializer instanceof ForumSerializer &&
|
||||
$event->relationship === 'tags') {
|
||||
return $event->serializer->hasMany('Flarum\Tags\Api\TagSerializer', 'tags');
|
||||
}
|
||||
|
||||
if ($event->serializer instanceof DiscussionSerializer &&
|
||||
$event->relationship === 'tags') {
|
||||
return $event->serializer->hasMany('Flarum\Tags\Api\TagSerializer', 'tags');
|
||||
}
|
||||
}
|
||||
|
||||
public function loadTagsRelationship(WillSerializeData $event)
|
||||
{
|
||||
// Expose the complete tag list to clients by adding it as a
|
||||
// relationship to the /api/forum endpoint. Since the Forum model
|
||||
// doesn't actually have a tags relationship, we will manually load and
|
||||
// assign the tags data to it using an event listener.
|
||||
if ($event->action instanceof Forum\ShowAction) {
|
||||
$forum = $event->data;
|
||||
|
||||
$query = Tag::whereVisibleTo($event->request->actor);
|
||||
|
||||
$forum->tags = $query->with('lastDiscussion')->get();
|
||||
$forum->tags_ids = $forum->tags->lists('id');
|
||||
}
|
||||
}
|
||||
|
||||
public function includeTagsRelationship(BuildApiAction $event)
|
||||
{
|
||||
if ($event->action instanceof Forum\ShowAction) {
|
||||
$event->addInclude('tags');
|
||||
$event->addInclude('tags.lastDiscussion');
|
||||
$event->addLink('tags.parent');
|
||||
}
|
||||
|
||||
if ($event->action instanceof Discussions\IndexAction ||
|
||||
$event->action instanceof Discussions\ShowAction ||
|
||||
$event->action instanceof Discussions\CreateAction) {
|
||||
$event->addInclude('tags');
|
||||
}
|
||||
|
||||
if ($event->action instanceof Discussions\CreateAction) {
|
||||
$event->addInclude('tags.lastDiscussion');
|
||||
}
|
||||
}
|
||||
|
||||
public function addAttributes(ApiAttributes $event)
|
||||
{
|
||||
if ($event->serializer instanceof DiscussionSerializer) {
|
||||
$event->attributes['canTag'] = $event->model->can($event->actor, 'tag');
|
||||
}
|
||||
|
||||
if ($event->serializer instanceof ForumSerializer) {
|
||||
$settings = app('Flarum\Core\Settings\SettingsRepository');
|
||||
|
||||
$event->attributes['minPrimaryTags'] = $settings->get('tags.min_primary_tags');
|
||||
$event->attributes['maxPrimaryTags'] = $settings->get('tags.max_primary_tags');
|
||||
$event->attributes['minSecondaryTags'] = $settings->get('tags.min_secondary_tags');
|
||||
$event->attributes['maxSecondaryTags'] = $settings->get('tags.max_secondary_tags');
|
||||
}
|
||||
}
|
||||
|
||||
public function addRoutes(RegisterApiRoutes $event)
|
||||
{
|
||||
$event->post('/tags', 'tags.create', 'Flarum\Tags\Api\CreateAction');
|
||||
$event->post('/tags/order', 'tags.order', 'Flarum\Tags\Api\OrderAction');
|
||||
$event->patch('/tags/{id}', 'tags.update', 'Flarum\Tags\Api\UpdateAction');
|
||||
$event->delete('/tags/{id}', 'tags.delete', 'Flarum\Tags\Api\DeleteAction');
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Listeners;
|
||||
|
||||
use Flarum\Events\ModelRelationship;
|
||||
use Flarum\Core\Discussions\Discussion;
|
||||
use Flarum\Tags\Tag;
|
||||
|
||||
class AddModelRelationship
|
||||
{
|
||||
public function subscribe($events)
|
||||
{
|
||||
$events->listen(ModelRelationship::class, [$this, 'addTagsRelationship']);
|
||||
}
|
||||
|
||||
public function addTagsRelationship(ModelRelationship $event)
|
||||
{
|
||||
if ($event->model instanceof Discussion &&
|
||||
$event->relationship === 'tags') {
|
||||
return $event->model->belongsToMany('Flarum\Tags\Tag', 'discussions_tags', null, null, 'tags');
|
||||
}
|
||||
}
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Listeners;
|
||||
|
||||
use Flarum\Events\ScopeModelVisibility;
|
||||
use Flarum\Events\ScopeHiddenDiscussionVisibility;
|
||||
use Flarum\Events\ModelAllow;
|
||||
use Flarum\Core\Discussions\Discussion;
|
||||
use Flarum\Tags\Tag;
|
||||
use Flarum\Reports\Report;
|
||||
use Illuminate\Database\Query\Expression;
|
||||
|
||||
class ConfigureDiscussionPermissions
|
||||
{
|
||||
public function subscribe($events)
|
||||
{
|
||||
$events->listen(ScopeModelVisibility::class, [$this, 'scopeDiscussionVisibility']);
|
||||
$events->listen(ScopeHiddenDiscussionVisibility::class, [$this, 'scopeHiddenDiscussionVisibility']);
|
||||
$events->listen(ModelAllow::class, [$this, 'allowDiscussionPermissions']);
|
||||
}
|
||||
|
||||
public function scopeDiscussionVisibility(ScopeModelVisibility $event)
|
||||
{
|
||||
// Hide discussions which have tags that the user is not allowed to see.
|
||||
if ($event->model instanceof Discussion) {
|
||||
$event->query->whereNotExists(function ($query) use ($event) {
|
||||
return $query->select(new Expression(1))
|
||||
->from('discussions_tags')
|
||||
->whereIn('tag_id', Tag::getIdsWhereCannot($event->actor, 'view'))
|
||||
->where('discussions.id', new Expression('discussion_id'));
|
||||
});
|
||||
}
|
||||
|
||||
if ($event->model instanceof Flag) {
|
||||
$event->query
|
||||
->select('flags.*')
|
||||
->leftJoin('posts', 'posts.id', '=', 'flags.post_id')
|
||||
->leftJoin('discussions', 'discussions.id', '=', 'posts.discussion_id')
|
||||
->whereNotExists(function ($query) use ($event) {
|
||||
return $query->select(new Expression(1))
|
||||
->from('discussions_tags')
|
||||
->whereIn('tag_id', Tag::getIdsWhereCannot($event->actor, 'discussion.viewFlags'))
|
||||
->where('discussions.id', new Expression('discussion_id'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public function scopeHiddenDiscussionVisibility(ScopeHiddenDiscussionVisibility $event)
|
||||
{
|
||||
// By default, discussions are not visible to the public if they are
|
||||
// hidden or contain zero comments - unless the actor has a certain
|
||||
// permission. Since we grant permissions per-tag, we will make
|
||||
// discussions visible in the tags for which the user has that
|
||||
// permission.
|
||||
$event->query->orWhereExists(function ($query) use ($event) {
|
||||
return $query->select(new Expression(1))
|
||||
->from('discussions_tags')
|
||||
->whereIn('tag_id', Tag::getIdsWhereCan($event->actor, $event->permission))
|
||||
->where('discussions.id', new Expression('discussion_id'));
|
||||
});
|
||||
}
|
||||
|
||||
public function allowDiscussionPermissions(ModelAllow $event)
|
||||
{
|
||||
// Wrap all discussion permission checks with some logic pertaining to
|
||||
// the discussion's tags. If the discussion has a tag that has been
|
||||
// restricted, and the user has this permission for that tag, then they
|
||||
// are allowed. If the discussion only has tags that have been
|
||||
// restricted, then the user *must* have permission for at least one of
|
||||
// them.
|
||||
if ($event->model instanceof Discussion) {
|
||||
$tags = $event->model->tags;
|
||||
|
||||
if (count($tags)) {
|
||||
$restricted = true;
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
if ($tag->is_restricted) {
|
||||
if ($event->actor->hasPermission('tag' . $tag->id . '.discussion.' . $event->action)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
$restricted = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($restricted) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Listeners;
|
||||
|
||||
use Flarum\Events\ScopeModelVisibility;
|
||||
use Flarum\Events\ModelAllow;
|
||||
use Flarum\Tags\Tag;
|
||||
|
||||
class ConfigureTagPermissions
|
||||
{
|
||||
public function subscribe($events)
|
||||
{
|
||||
$events->listen(ScopeModelVisibility::class, [$this, 'scopeTagVisibility']);
|
||||
$events->listen(ModelAllow::class, [$this, 'allowStartDiscussion']);
|
||||
}
|
||||
|
||||
public function scopeTagVisibility(ScopeModelVisibility $event)
|
||||
{
|
||||
if ($event->model instanceof Tag) {
|
||||
$event->query->whereNotIn('id', Tag::getIdsWhereCannot($event->actor, 'view'));
|
||||
}
|
||||
}
|
||||
|
||||
public function allowStartDiscussion(ModelAllow $event)
|
||||
{
|
||||
if ($event->model instanceof Tag) {
|
||||
if (! $event->model->is_restricted ||
|
||||
$event->actor->hasPermission('tag' . $event->model->id . '.startDiscussion')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -8,16 +8,22 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Flarum\Tags\Posts;
|
||||
namespace Flarum\Tags\Post;
|
||||
|
||||
use Flarum\Core\Posts\Post;
|
||||
use Flarum\Core\Posts\EventPost;
|
||||
use Flarum\Core\Posts\MergeablePost;
|
||||
use Flarum\Core\Post;
|
||||
use Flarum\Core\Post\AbstractEventPost;
|
||||
use Flarum\Core\Post\MergeableInterface;
|
||||
|
||||
class DiscussionTaggedPost extends EventPost implements MergeablePost
|
||||
class DiscussionTaggedPost extends AbstractEventPost implements MergeableInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $type = 'discussionTagged';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function saveAfter(Post $previous)
|
||||
{
|
||||
// If the previous post is another 'discussion tagged' post, and it's
|
@ -10,32 +10,27 @@
|
||||
|
||||
namespace Flarum\Tags;
|
||||
|
||||
use Flarum\Core\Model;
|
||||
use Flarum\Core\Discussions\Discussion;
|
||||
use Flarum\Core\Groups\Permission;
|
||||
use Flarum\Core\Support\VisibleScope;
|
||||
use Flarum\Core\Support\Locked;
|
||||
use Flarum\Core\Support\ValidatesBeforeSave;
|
||||
use Flarum\Core\Discussion;
|
||||
use Flarum\Core\Permission;
|
||||
use Flarum\Core\Support\ScopeVisibilityTrait;
|
||||
use Flarum\Database\AbstractModel;
|
||||
|
||||
class Tag extends Model
|
||||
class Tag extends AbstractModel
|
||||
{
|
||||
use ValidatesBeforeSave;
|
||||
use VisibleScope;
|
||||
use Locked;
|
||||
|
||||
protected $table = 'tags';
|
||||
|
||||
protected $dates = ['last_time'];
|
||||
|
||||
protected $rules = [
|
||||
'name' => 'required',
|
||||
'slug' => ['required', 'unique:slug']
|
||||
];
|
||||
use ScopeVisibilityTrait;
|
||||
|
||||
/**
|
||||
* Boot the model.
|
||||
*
|
||||
* @return void
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $table = 'tags';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $dates = ['last_time'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function boot()
|
||||
{
|
||||
@ -71,19 +66,28 @@ class Tag extends Model
|
||||
return $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function parent()
|
||||
{
|
||||
return $this->belongsTo('Flarum\Tags\Tag', 'parent_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function lastDiscussion()
|
||||
{
|
||||
return $this->belongsTo('Flarum\Core\Discussions\Discussion', 'last_discussion_id');
|
||||
return $this->belongsTo('Flarum\Core\Discussion', 'last_discussion_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function discussions()
|
||||
{
|
||||
return $this->belongsToMany('Flarum\Core\Discussions\Discussion', 'discussions_tags');
|
||||
return $this->belongsToMany('Flarum\Core\Discussion', 'discussions_tags');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -114,6 +118,11 @@ class Tag extends Model
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $user
|
||||
* @param $permission
|
||||
* @return array
|
||||
*/
|
||||
public static function getIdsWhereCan($user, $permission)
|
||||
{
|
||||
static $tags;
|
||||
@ -134,6 +143,11 @@ class Tag extends Model
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $user
|
||||
* @param $permission
|
||||
* @return array
|
||||
*/
|
||||
public static function getIdsWhereCannot($user, $permission)
|
||||
{
|
||||
static $tags;
|
||||
|
@ -10,9 +10,8 @@
|
||||
|
||||
namespace Flarum\Tags;
|
||||
|
||||
use Flarum\Core\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Flarum\Core\Users\User;
|
||||
use Flarum\Tags\Tag;
|
||||
|
||||
class TagRepository
|
||||
{
|
||||
@ -23,7 +22,6 @@ class TagRepository
|
||||
* @param int $id
|
||||
* @param User $actor
|
||||
* @return Tag
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function findOrFail($id, User $actor = null)
|
||||
|
@ -10,8 +10,15 @@
|
||||
|
||||
namespace Flarum\Tags;
|
||||
|
||||
use Flarum\Core\Exceptions\ValidationException;
|
||||
use Flarum\Core\Validator\AbstractValidator;
|
||||
|
||||
class TagCountException extends ValidationException
|
||||
class TagValidator extends AbstractValidator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $rules = [
|
||||
'name' => ['required'],
|
||||
'slug' => ['required', 'unique:slug']
|
||||
];
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user