mirror of
https://github.com/flarum/framework.git
synced 2024-12-13 07:03:35 +08:00
New user activity feed API.
Originally the user activity feed was implemented using UNIONs. I was looking at make an API to add activity “sources”, or extra UNION queries (select from posts, mentions, etc.) but quickly realised that this is too slow and there’s no way to make it scale. So I’ve implemented an API which is very similar to how notifications work (see previous commit). The `activity` table is an aggregation of stuff that happens, and it’s kept in sync by an ActivitySyncer which is used whenever a post it created/edited/deleted, a user is mentioned/unmentioned, etc. Again, the API is very simple (see Core\Activity\PostedActivity + Core\Handlers\Events\UserActivitySyncer)
This commit is contained in:
parent
8edb684ea9
commit
500c279fb3
|
@ -2,7 +2,7 @@ import Component from 'flarum/component';
|
|||
import humanTime from 'flarum/helpers/human-time';
|
||||
import avatar from 'flarum/helpers/avatar';
|
||||
|
||||
export default class JoinActivity extends Component {
|
||||
export default class JoinedActivity extends Component {
|
||||
view() {
|
||||
var activity = this.props.activity;
|
||||
var user = activity.user();
|
|
@ -4,11 +4,11 @@ import avatar from 'flarum/helpers/avatar';
|
|||
import listItems from 'flarum/helpers/list-items';
|
||||
import ItemList from 'flarum/utils/item-list';
|
||||
|
||||
export default class PostActivity extends Component {
|
||||
export default class PostedActivity extends Component {
|
||||
view() {
|
||||
var activity = this.props.activity;
|
||||
var user = activity.user();
|
||||
var post = activity.post();
|
||||
var post = activity.subject();
|
||||
var discussion = post.discussion();
|
||||
|
||||
return m('div', [
|
||||
|
@ -23,7 +23,7 @@ export default class PostActivity extends Component {
|
|||
near: post.number()
|
||||
}), config: m.route}, [
|
||||
m('ul.list-inline', listItems(this.headerItems().toArray())),
|
||||
m('div.body', m.trust(post.contentHtml()))
|
||||
m('div.body', m.trust(post.excerpt()))
|
||||
])
|
||||
]);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ export default class PostActivity extends Component {
|
|||
headerItems() {
|
||||
var items = new ItemList();
|
||||
|
||||
items.add('title', m('h3.title', this.props.activity.post().discussion().title()));
|
||||
items.add('title', m('h3.title', this.props.activity.subject().discussion().title()));
|
||||
|
||||
return items;
|
||||
}
|
|
@ -1,21 +1,22 @@
|
|||
import CommentPost from 'flarum/components/comment-post';
|
||||
import DiscussionRenamedPost from 'flarum/components/discussion-renamed-post';
|
||||
import PostActivity from 'flarum/components/post-activity';
|
||||
import JoinActivity from 'flarum/components/join-activity';
|
||||
import PostedActivity from 'flarum/components/posted-activity';
|
||||
import JoinedActivity from 'flarum/components/joined-activity';
|
||||
import DiscussionRenamedNotification from 'flarum/components/discussion-renamed-notification';
|
||||
|
||||
export default function(app) {
|
||||
app.postComponentRegistry = {
|
||||
comment: CommentPost,
|
||||
discussionRenamed: DiscussionRenamedPost
|
||||
'comment': CommentPost,
|
||||
'discussionRenamed': DiscussionRenamedPost
|
||||
};
|
||||
|
||||
app.activityComponentRegistry = {
|
||||
post: PostActivity,
|
||||
join: JoinActivity
|
||||
'posted': PostedActivity,
|
||||
'startedDiscussion': PostedActivity,
|
||||
'joined': JoinedActivity
|
||||
};
|
||||
|
||||
app.notificationComponentRegistry = {
|
||||
discussionRenamed: DiscussionRenamedNotification
|
||||
'discussionRenamed': DiscussionRenamedNotification
|
||||
};
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ export default function(app) {
|
|||
|
||||
'user': ['/u/:username', ActivityPage.component()],
|
||||
'user.activity': ['/u/:username', ActivityPage.component()],
|
||||
'user.discussions': ['/u/:username/discussions', ActivityPage.component({filter: 'discussion'})],
|
||||
'user.posts': ['/u/:username/posts', ActivityPage.component({filter: 'post'})],
|
||||
'user.discussions': ['/u/:username/discussions', ActivityPage.component({filter: 'startedDiscussion'})],
|
||||
'user.posts': ['/u/:username/posts', ActivityPage.component({filter: 'posted'})],
|
||||
|
||||
'settings': ['/settings', SettingsPage.component()]
|
||||
};
|
||||
|
|
|
@ -8,7 +8,6 @@ Activity.prototype.content = Model.prop('content');
|
|||
Activity.prototype.time = Model.prop('time', Model.date);
|
||||
|
||||
Activity.prototype.user = Model.one('user');
|
||||
Activity.prototype.sender = Model.one('sender');
|
||||
Activity.prototype.post = Model.one('post');
|
||||
Activity.prototype.subject = Model.one('subject');
|
||||
|
||||
export default Activity;
|
||||
|
|
|
@ -14,11 +14,10 @@ class CreateActivityTable extends Migration
|
|||
public function up()
|
||||
{
|
||||
Schema::create('activity', function (Blueprint $table) {
|
||||
|
||||
$table->increments('id');
|
||||
$table->integer('user_id')->unsigned();
|
||||
$table->integer('sender_id')->unsigned()->nullable();
|
||||
$table->string('type', 100);
|
||||
$table->integer('subject_id')->unsigned()->nullable();
|
||||
$table->binary('data')->nullable();
|
||||
$table->dateTime('time');
|
||||
});
|
||||
|
|
|
@ -32,12 +32,9 @@ class IndexAction extends SerializeCollectionAction
|
|||
* @var array
|
||||
*/
|
||||
public static $include = [
|
||||
'sender' => true,
|
||||
'post' => true,
|
||||
'post.user' => true,
|
||||
'post.discussion' => true,
|
||||
'post.discussion.startUser' => true,
|
||||
'post.discussion.lastUser' => true
|
||||
'subject' => true,
|
||||
'subject.user' => true,
|
||||
'subject.discussion' => true
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -73,6 +70,7 @@ class IndexAction extends SerializeCollectionAction
|
|||
|
||||
$user = $this->users->findOrFail($request->get('users'), $actor);
|
||||
|
||||
return $this->activity->findByUser($user->id, $actor, $request->limit, $request->offset, $request->get('type'));
|
||||
return $this->activity->findByUser($user->id, $actor, $request->limit, $request->offset, $request->get('type'))
|
||||
->load($request->include);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,17 @@ class ActivitySerializer extends BaseSerializer
|
|||
*/
|
||||
protected $type = 'activity';
|
||||
|
||||
/**
|
||||
* A map of activity types (key) to the serializer that should be used to
|
||||
* output the activity's subject (value).
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $subjects = [
|
||||
'posted' => 'Flarum\Api\Serializers\PostBasicSerializer',
|
||||
'joined' => 'Flarum\Api\Serializers\UserBasicSerializer'
|
||||
];
|
||||
|
||||
/**
|
||||
* Serialize attributes of an Activity model for JSON output.
|
||||
*
|
||||
|
@ -18,9 +29,7 @@ class ActivitySerializer extends BaseSerializer
|
|||
protected function attributes($activity)
|
||||
{
|
||||
$attributes = [
|
||||
'id' => ((int) $activity->id) ?: str_random(5),
|
||||
'contentType' => $activity->type,
|
||||
'content' => json_encode($activity->data),
|
||||
'time' => $activity->time->toRFC3339String()
|
||||
];
|
||||
|
||||
|
@ -37,8 +46,10 @@ class ActivitySerializer extends BaseSerializer
|
|||
return $this->hasOne('Flarum\Api\Serializers\UserBasicSerializer');
|
||||
}
|
||||
|
||||
public function post()
|
||||
public function subject()
|
||||
{
|
||||
return $this->hasOne('Flarum\Api\Serializers\PostSerializer');
|
||||
return $this->hasOne(function ($activity) {
|
||||
return static::$subjects[$activity->type];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
5
framework/core/src/Core/Activity/ActivityAbstract.php
Normal file
5
framework/core/src/Core/Activity/ActivityAbstract.php
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?php namespace Flarum\Core\Activity;
|
||||
|
||||
abstract class ActivityAbstract implements ActivityInterface
|
||||
{
|
||||
}
|
32
framework/core/src/Core/Activity/ActivityInterface.php
Normal file
32
framework/core/src/Core/Activity/ActivityInterface.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php namespace Flarum\Core\Activity;
|
||||
|
||||
interface ActivityInterface
|
||||
{
|
||||
/**
|
||||
* Get the model that is the subject of this activity.
|
||||
*
|
||||
* @return \Flarum\Core\Models\Model
|
||||
*/
|
||||
public function getSubject();
|
||||
|
||||
/**
|
||||
* Get the time at which the activity occurred.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTime();
|
||||
|
||||
/**
|
||||
* Get the serialized type of this activity.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getType();
|
||||
|
||||
/**
|
||||
* Get the name of the model class for the subject of this activity.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getSubjectModel();
|
||||
}
|
53
framework/core/src/Core/Activity/ActivitySyncer.php
Normal file
53
framework/core/src/Core/Activity/ActivitySyncer.php
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?php namespace Flarum\Core\Activity;
|
||||
|
||||
use Flarum\Core\Repositories\ActivityRepositoryInterface;
|
||||
use Flarum\Core\Models\Activity;
|
||||
|
||||
class ActivitySyncer
|
||||
{
|
||||
protected $activity;
|
||||
|
||||
public function __construct(ActivityRepositoryInterface $activity)
|
||||
{
|
||||
$this->activity = $activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync a piece of activity so that it is present for the specified users,
|
||||
* and not present for anyone else.
|
||||
*
|
||||
* @param \Flarum\Core\Activity\ActivityInterface $activity
|
||||
* @param \Flarum\Core\Models\User[] $users
|
||||
* @return void
|
||||
*/
|
||||
public function sync(ActivityInterface $activity, array $users)
|
||||
{
|
||||
Activity::unguard();
|
||||
|
||||
$attributes = [
|
||||
'type' => $activity::getType(),
|
||||
'subject_id' => $activity->getSubject()->id,
|
||||
'time' => $activity->getTime()
|
||||
];
|
||||
|
||||
$toDelete = Activity::where($attributes)->get();
|
||||
$toInsert = [];
|
||||
|
||||
foreach ($users as $user) {
|
||||
$existing = $toDelete->where('user_id', $user->id)->first();
|
||||
|
||||
if ($k = $toDelete->search($existing)) {
|
||||
$toDelete->pull($k);
|
||||
} else {
|
||||
$toInsert[] = $attributes + ['user_id' => $user->id];
|
||||
}
|
||||
}
|
||||
|
||||
if (count($toDelete)) {
|
||||
Activity::whereIn('id', $toDelete->lists('id'))->delete();
|
||||
}
|
||||
if (count($toInsert)) {
|
||||
Activity::insert($toInsert);
|
||||
}
|
||||
}
|
||||
}
|
33
framework/core/src/Core/Activity/JoinedActivity.php
Normal file
33
framework/core/src/Core/Activity/JoinedActivity.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php namespace Flarum\Core\Activity;
|
||||
|
||||
use Flarum\Core\Models\User;
|
||||
|
||||
class JoinedActivity extends ActivityAbstract
|
||||
{
|
||||
protected $user;
|
||||
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
public function getSubject()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function getTime()
|
||||
{
|
||||
return $this->user->join_time;
|
||||
}
|
||||
|
||||
public static function getType()
|
||||
{
|
||||
return 'joined';
|
||||
}
|
||||
|
||||
public static function getSubjectModel()
|
||||
{
|
||||
return 'Flarum\Core\Models\User';
|
||||
}
|
||||
}
|
33
framework/core/src/Core/Activity/PostedActivity.php
Normal file
33
framework/core/src/Core/Activity/PostedActivity.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php namespace Flarum\Core\Activity;
|
||||
|
||||
use Flarum\Core\Models\Post;
|
||||
|
||||
class PostedActivity extends ActivityAbstract
|
||||
{
|
||||
protected $post;
|
||||
|
||||
public function __construct(Post $post)
|
||||
{
|
||||
$this->post = $post;
|
||||
}
|
||||
|
||||
public function getSubject()
|
||||
{
|
||||
return $this->post;
|
||||
}
|
||||
|
||||
public function getTime()
|
||||
{
|
||||
return $this->post->time;
|
||||
}
|
||||
|
||||
public static function getType()
|
||||
{
|
||||
return 'posted';
|
||||
}
|
||||
|
||||
public static function getSubjectModel()
|
||||
{
|
||||
return 'Flarum\Core\Models\Post';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<?php namespace Flarum\Core\Activity;
|
||||
|
||||
class StartedDiscussionActivity extends PostedActivity
|
||||
{
|
||||
public static function getType()
|
||||
{
|
||||
return 'startedDiscussion';
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ use League\Flysystem\Adapter\Local;
|
|||
use Flarum\Core\Events\RegisterDiscussionGambits;
|
||||
use Flarum\Core\Events\RegisterUserGambits;
|
||||
use Flarum\Extend\Permission;
|
||||
use Flarum\Extend\ActivityType;
|
||||
use Flarum\Extend\NotificationType;
|
||||
|
||||
class CoreServiceProvider extends ServiceProvider
|
||||
|
@ -46,9 +47,16 @@ class CoreServiceProvider extends ServiceProvider
|
|||
});
|
||||
|
||||
$events->subscribe('Flarum\Core\Handlers\Events\DiscussionRenamedNotifier');
|
||||
$events->subscribe('Flarum\Core\Handlers\Events\UserActivitySyncer');
|
||||
|
||||
$this->extend(
|
||||
(new NotificationType('Flarum\Core\Notifications\DiscussionRenamedNotification', 'Flarum\Api\Serializers\DiscussionBasicSerializer'))
|
||||
->enableByDefault('alert'),
|
||||
|
||||
(new ActivityType('Flarum\Core\Activity\PostedActivity', 'Flarum\Api\Serializers\PostBasicSerializer')),
|
||||
(new ActivityType('Flarum\Core\Activity\StartedDiscussionActivity', 'Flarum\Api\Serializers\PostBasicSerializer')),
|
||||
|
||||
(new ActivityType('Flarum\Core\Activity\JoinedActivity', 'Flarum\Api\Serializers\UserBasicSerializer'))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
76
framework/core/src/Core/Handlers/Events/UserActivitySyncer.php
Executable file
76
framework/core/src/Core/Handlers/Events/UserActivitySyncer.php
Executable file
|
@ -0,0 +1,76 @@
|
|||
<?php namespace Flarum\Core\Handlers\Events;
|
||||
|
||||
use Flarum\Core\Activity\ActivitySyncer;
|
||||
use Flarum\Core\Activity\PostedActivity;
|
||||
use Flarum\Core\Activity\StartedDiscussionActivity;
|
||||
use Flarum\Core\Activity\JoinedActivity;
|
||||
use Flarum\Core\Events\PostWasPosted;
|
||||
use Flarum\Core\Events\PostWasDeleted;
|
||||
use Flarum\Core\Events\PostWasHidden;
|
||||
use Flarum\Core\Events\PostWasRestored;
|
||||
use Flarum\Core\Events\UserWasRegistered;
|
||||
use Flarum\Core\Models\Post;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
class UserActivitySyncer
|
||||
{
|
||||
protected $activity;
|
||||
|
||||
public function __construct(ActivitySyncer $activity)
|
||||
{
|
||||
$this->activity = $activity;
|
||||
}
|
||||
|
||||
public function subscribe(Dispatcher $events)
|
||||
{
|
||||
$events->listen('Flarum\Core\Events\PostWasPosted', __CLASS__.'@whenPostWasPosted');
|
||||
$events->listen('Flarum\Core\Events\PostWasHidden', __CLASS__.'@whenPostWasHidden');
|
||||
$events->listen('Flarum\Core\Events\PostWasRestored', __CLASS__.'@whenPostWasRestored');
|
||||
$events->listen('Flarum\Core\Events\PostWasDeleted', __CLASS__.'@whenPostWasDeleted');
|
||||
$events->listen('Flarum\Core\Events\UserWasRegistered', __CLASS__.'@whenUserWasRegistered');
|
||||
}
|
||||
|
||||
public function whenPostWasPosted(PostWasPosted $event)
|
||||
{
|
||||
$this->postBecameVisible($event->post);
|
||||
}
|
||||
|
||||
public function whenPostWasHidden(PostWasHidden $event)
|
||||
{
|
||||
$this->postBecameInvisible($event->post);
|
||||
}
|
||||
|
||||
public function whenPostWasRestored(PostWasRestored $event)
|
||||
{
|
||||
$this->postBecameVisible($event->post);
|
||||
}
|
||||
|
||||
public function whenPostWasDeleted(PostWasDeleted $event)
|
||||
{
|
||||
$this->postBecameInvisible($event->post);
|
||||
}
|
||||
|
||||
public function whenUserWasRegistered(UserWasRegistered $event)
|
||||
{
|
||||
$this->activity->sync(new JoinedActivity($event->user), [$event->user]);
|
||||
}
|
||||
|
||||
protected function postBecameVisible(Post $post)
|
||||
{
|
||||
$activity = $this->postedActivity($post);
|
||||
|
||||
$this->activity->sync($activity, [$post->user]);
|
||||
}
|
||||
|
||||
protected function postBecameInvisible(Post $post)
|
||||
{
|
||||
$activity = $this->postedActivity($post);
|
||||
|
||||
$this->activity->sync($activity, []);
|
||||
}
|
||||
|
||||
protected function postedActivity(Post $post)
|
||||
{
|
||||
return $post->number === 1 ? new StartedDiscussionActivity($post) : new PostedActivity($post);
|
||||
}
|
||||
}
|
|
@ -16,6 +16,13 @@ class Activity extends Model
|
|||
*/
|
||||
protected $dates = ['time'];
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $subjects = [];
|
||||
|
||||
/**
|
||||
* Unserialize the data attribute.
|
||||
*
|
||||
|
@ -47,23 +54,27 @@ class Activity extends Model
|
|||
return $this->belongsTo('Flarum\Core\Models\User', 'user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the relationship with the activity's sender.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function sender()
|
||||
public function subject()
|
||||
{
|
||||
return $this->belongsTo('Flarum\Core\Models\User', 'sender_id');
|
||||
return $this->mappedMorphTo(static::$subjects, 'subject', 'type', 'subject_id');
|
||||
}
|
||||
|
||||
public static function getTypes()
|
||||
{
|
||||
return static::$subjects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the relationship with the activity's sender.
|
||||
* Register a notification type.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
* @param string $type
|
||||
* @param string $class
|
||||
* @return void
|
||||
*/
|
||||
public function post()
|
||||
public static function registerType($class)
|
||||
{
|
||||
return $this->belongsTo('Flarum\Core\Models\Post', 'post_id');
|
||||
if ($subject = $class::getSubjectModel()) {
|
||||
static::$subjects[$class::getType()] = $subject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
<?php namespace Flarum\Core\Notifications\Types;
|
||||
|
||||
interface AlertableNotification
|
||||
{
|
||||
/**
|
||||
* Get the data to be stored in the alert.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAlertData();
|
||||
|
||||
/**
|
||||
* Get the user that sent the notification.
|
||||
*
|
||||
* @return \Flarum\Core\Models\User|null
|
||||
*/
|
||||
public function getSender();
|
||||
|
||||
/**
|
||||
* Get the model that the notification is about.
|
||||
*
|
||||
* @return \Flarum\Core\Models\Model
|
||||
*/
|
||||
public function getSubject();
|
||||
|
||||
/**
|
||||
* Get the class name of this notification type's subject model.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getSubjectModel();
|
||||
}
|
|
@ -1,39 +1,22 @@
|
|||
<?php namespace Flarum\Core\Repositories;
|
||||
|
||||
use Flarum\Core\Models\Activity;
|
||||
use Flarum\Core\Models\Post;
|
||||
use Flarum\Core\Models\User;
|
||||
|
||||
class EloquentActivityRepository implements ActivityRepositoryInterface
|
||||
{
|
||||
public function findByUser($userId, User $viewer, $count = null, $start = 0, $type = null)
|
||||
public function findByUser($userId, User $viewer, $limit = null, $offset = 0, $type = null)
|
||||
{
|
||||
// This is all very rough and needs to be cleaned up
|
||||
$query = Activity::where('user_id', $userId)
|
||||
->whereIn('type', array_keys(Activity::getTypes()))
|
||||
->orderBy('time', 'desc')
|
||||
->skip($offset)
|
||||
->take($limit);
|
||||
|
||||
$null = \DB::raw('NULL');
|
||||
$query = Activity::with('sender')->select('id', 'user_id', 'sender_id', 'type', 'data', 'time', \DB::raw('NULL as post_id'))->where('user_id', $userId);
|
||||
|
||||
if ($type) {
|
||||
if ($type !== null) {
|
||||
$query->where('type', $type);
|
||||
}
|
||||
|
||||
$posts = Post::whereCan($viewer, 'view')->with('post', 'post.discussion', 'post.user', 'post.discussion.startUser', 'post.discussion.lastUser')->select(\DB::raw("CONCAT('post', id)"), 'user_id', $null, \DB::raw("'post'"), $null, 'time', 'id')->where('user_id', $userId)->where('type', 'comment')->whereNull('hide_time');
|
||||
|
||||
if ($type === 'post') {
|
||||
$posts->where('number', '>', 1);
|
||||
} elseif ($type === 'discussion') {
|
||||
$posts->where('number', 1);
|
||||
}
|
||||
|
||||
if (!$type) {
|
||||
$join = User::select(\DB::raw("CONCAT('join', id)"), 'id', 'id', \DB::raw("'join'"), $null, 'join_time', $null)->where('id', $userId);
|
||||
$query->union($join->getQuery());
|
||||
}
|
||||
|
||||
return $query->union($posts->getQuery())
|
||||
->orderBy('time', 'desc')
|
||||
->skip($start)
|
||||
->take($count)
|
||||
->get();
|
||||
return $query->get();
|
||||
}
|
||||
}
|
||||
|
|
27
framework/core/src/Extend/ActivityType.php
Normal file
27
framework/core/src/Extend/ActivityType.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php namespace Flarum\Extend;
|
||||
|
||||
use Illuminate\Foundation\Application;
|
||||
use Flarum\Core\Models\Activity;
|
||||
use Flarum\Api\Serializers\ActivitySerializer;
|
||||
|
||||
class ActivityType implements ExtenderInterface
|
||||
{
|
||||
protected $class;
|
||||
|
||||
protected $serializer;
|
||||
|
||||
public function __construct($class, $serializer)
|
||||
{
|
||||
$this->class = $class;
|
||||
$this->serializer = $serializer;
|
||||
}
|
||||
|
||||
public function extend(Application $app)
|
||||
{
|
||||
$class = $this->class;
|
||||
|
||||
Activity::registerType($class);
|
||||
|
||||
ActivitySerializer::$subjects[$class::getType()] = $this->serializer;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user