From 659ca692e386db2c76c0693e3fcaf8d1a5784696 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Wed, 1 Jul 2015 22:34:11 +0930 Subject: [PATCH] Refactor CoreServiceProvider A good start I think, but still some work to do. If we go ahead with https://github.com/flarum/core/issues/132#issuecomment-117507974 (which I am in favour of), we can extract the entity-related stuff into some smaller service providers (e.g. discussion repo, an event listener, permissions, and gambits stuff could all go in Flarum\Core\Discussions\DiscussionsServiceProvider). --- framework/core/src/Api/ApiServiceProvider.php | 2 + .../Api/Serializers/ActivitySerializer.php | 14 +- .../Core/Activity/ActivityServiceProvider.php | 36 ++++ .../core/src/Core/CoreServiceProvider.php | 162 +++++++++--------- .../Core/Events/RegisterDiscussionGambits.php | 13 -- .../src/Core/Events/RegisterUserGambits.php | 13 -- .../Formatter/FormatterServiceProvider.php | 29 ++++ .../NotificationsServiceProvider.php | 31 ++++ .../core/src/Core/Support/MappedMorphTo.php | 44 ----- .../src/Core/Support/MappedMorphToTrait.php | 49 ------ framework/core/src/Extend/ActivityType.php | 15 +- .../core/src/Extend/DiscussionGambit.php | 4 +- .../core/src/Extend/NotificationType.php | 8 +- .../core/src/Forum/ForumServiceProvider.php | 2 + .../core/src/Locale/LocaleServiceProvider.php | 34 ++++ 15 files changed, 239 insertions(+), 217 deletions(-) create mode 100644 framework/core/src/Core/Activity/ActivityServiceProvider.php delete mode 100644 framework/core/src/Core/Events/RegisterDiscussionGambits.php delete mode 100644 framework/core/src/Core/Events/RegisterUserGambits.php create mode 100644 framework/core/src/Core/Formatter/FormatterServiceProvider.php create mode 100644 framework/core/src/Core/Notifications/NotificationsServiceProvider.php delete mode 100644 framework/core/src/Core/Support/MappedMorphTo.php delete mode 100644 framework/core/src/Core/Support/MappedMorphToTrait.php create mode 100644 framework/core/src/Locale/LocaleServiceProvider.php diff --git a/framework/core/src/Api/ApiServiceProvider.php b/framework/core/src/Api/ApiServiceProvider.php index f032eb790..591b47b5f 100644 --- a/framework/core/src/Api/ApiServiceProvider.php +++ b/framework/core/src/Api/ApiServiceProvider.php @@ -22,6 +22,8 @@ class ApiServiceProvider extends ServiceProvider return new UrlGenerator($this->app->make('flarum.api.routes')); } ); + + $this->app->register('Flarum\Locale\LocaleServiceProvider'); } /** diff --git a/framework/core/src/Api/Serializers/ActivitySerializer.php b/framework/core/src/Api/Serializers/ActivitySerializer.php index 4dd10b8c9..907932112 100644 --- a/framework/core/src/Api/Serializers/ActivitySerializer.php +++ b/framework/core/src/Api/Serializers/ActivitySerializer.php @@ -3,9 +3,7 @@ class ActivitySerializer extends BaseSerializer { /** - * The resource type. - * - * @var string + * @inheritdoc */ protected $type = 'activity'; @@ -15,10 +13,7 @@ class ActivitySerializer extends BaseSerializer * * @var array */ - public static $subjects = [ - 'posted' => 'Flarum\Api\Serializers\PostBasicSerializer', - 'joined' => 'Flarum\Api\Serializers\UserBasicSerializer' - ]; + protected static $subjectSerializers = []; /** * Serialize attributes of an Activity model for JSON output. @@ -52,4 +47,9 @@ class ActivitySerializer extends BaseSerializer return static::$subjects[$activity->type]; }); } + + public static function setSubjectSerializer($type, $serializer) + { + static::$subjectSerializers[$type] = $serializer; + } } diff --git a/framework/core/src/Core/Activity/ActivityServiceProvider.php b/framework/core/src/Core/Activity/ActivityServiceProvider.php new file mode 100644 index 000000000..3a9affe96 --- /dev/null +++ b/framework/core/src/Core/Activity/ActivityServiceProvider.php @@ -0,0 +1,36 @@ +extend([ + (new Extend\EventSubscriber('Flarum\Core\Handlers\Events\UserActivitySyncer')), + + (new Extend\ActivityType('Flarum\Core\Activity\PostedActivity')) + ->subjectSerializer('Flarum\Api\Serializers\PostBasicSerializer'), + + (new Extend\ActivityType('Flarum\Core\Activity\StartedDiscussionActivity')) + ->subjectSerializer('Flarum\Api\Serializers\PostBasicSerializer'), + + (new Extend\ActivityType('Flarum\Core\Activity\JoinedActivity')) + ->subjectSerializer('Flarum\Api\Serializers\UserBasicSerializer') + ]); + } + + public function register() + { + $this->app->bind( + 'Flarum\Core\Repositories\ActivityRepositoryInterface', + 'Flarum\Core\Repositories\EloquentActivityRepository' + ); + } +} diff --git a/framework/core/src/Core/CoreServiceProvider.php b/framework/core/src/Core/CoreServiceProvider.php index 5799d140b..97b44b589 100644 --- a/framework/core/src/Core/CoreServiceProvider.php +++ b/framework/core/src/Core/CoreServiceProvider.php @@ -2,7 +2,6 @@ use Illuminate\Bus\Dispatcher as Bus; use Illuminate\Contracts\Container\Container; -use Illuminate\Contracts\Events\Dispatcher; use Flarum\Support\ServiceProvider; use Flarum\Core\Models\CommentPost; use Flarum\Core\Models\Post; @@ -11,11 +10,7 @@ use Flarum\Core\Models\Forum; use Flarum\Core\Models\User; use Flarum\Core\Models\Discussion; use Flarum\Core\Search\GambitManager; -use Flarum\Core\Events\RegisterDiscussionGambits; -use Flarum\Core\Events\RegisterUserGambits; -use Flarum\Extend\ActivityType; -use Flarum\Extend\NotificationType; -use Flarum\Extend\Locale; +use Flarum\Extend; class CoreServiceProvider extends ServiceProvider { @@ -24,47 +19,26 @@ class CoreServiceProvider extends ServiceProvider * * @return void */ - public function boot(Dispatcher $events, Bus $bus) + public function boot() { $this->loadViewsFrom(__DIR__.'/../../views', 'flarum'); - $this->registerEventHandlers($events); - $this->registerPostTypes(); - $this->registerPermissions(); - $this->registerGambits(); - $this->setupModels(); + $this->addEventHandlers(); + $this->bootModels(); + $this->addPostTypes(); + $this->grantPermissions(); + $this->mapCommandHandlers(); + } - $this->app['flarum.formatter']->add('linkify', 'Flarum\Core\Formatter\LinkifyFormatter'); - - $bus->mapUsing(function ($command) { + public function mapCommandHandlers() + { + $this->app->make(Bus::class)->mapUsing(function ($command) { return Bus::simpleMapping( $command, 'Flarum\Core\Commands', 'Flarum\Core\Handlers\Commands' ); }); - - $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')) - ); - - foreach (['en'] as $locale) { - $dir = __DIR__.'/../../locale/'.$locale; - - $this->extend( - (new Locale($locale)) - ->translations($dir.'/translations.yml') - ->config($dir.'/config.php') - ->js($dir.'/config.js') - ); - } } /** @@ -76,101 +50,121 @@ class CoreServiceProvider extends ServiceProvider { // Register a singleton entity that represents this forum. This entity // will be used to check for global forum permissions (like viewing the - // forum, registering, and starting discussions.) + // forum, registering, and starting discussions). $this->app->singleton('flarum.forum', 'Flarum\Core\Models\Forum'); - $this->app->singleton('flarum.formatter', 'Flarum\Core\Formatter\FormatterManager'); - - $this->app->singleton('flarum.localeManager', 'Flarum\Locale\LocaleManager'); - - $this->app->singleton('Flarum\Support\Actor'); + // TODO: probably use Illuminate's AggregateServiceProvider + // functionality, because it includes the 'provides' stuff. + $this->app->register('Flarum\Core\Activity\ActivityServiceProvider'); + $this->app->register('Flarum\Core\Formatter\FormatterServiceProvider'); + $this->app->register('Flarum\Core\Notifications\NotificationsServiceProvider'); + // TODO: refactor these into the appropriate service providers, when + // (if) we restructure our namespaces per-entity + // (Flarum\Core\Discussions\DiscussionsServiceProvider, etc.) $this->app->bind( 'Flarum\Core\Repositories\DiscussionRepositoryInterface', 'Flarum\Core\Repositories\EloquentDiscussionRepository' ); + $this->app->bind( 'Flarum\Core\Repositories\PostRepositoryInterface', 'Flarum\Core\Repositories\EloquentPostRepository' ); + $this->app->bind( 'Flarum\Core\Repositories\UserRepositoryInterface', 'Flarum\Core\Repositories\EloquentUserRepository' ); - $this->app->bind( - 'Flarum\Core\Repositories\ActivityRepositoryInterface', - 'Flarum\Core\Repositories\EloquentActivityRepository' - ); $this->app->bind( 'Flarum\Core\Search\Discussions\Fulltext\DriverInterface', 'Flarum\Core\Search\Discussions\Fulltext\MySqlFulltextDriver' ); - $avatarFilesystem = function (Container $app) { + $this->registerDiscussionGambits(); + $this->registerUserGambits(); + $this->registerAvatarsFilesystem(); + } + + public function registerAvatarsFilesystem() + { + $avatarsFilesystem = function (Container $app) { return $app->make('Illuminate\Contracts\Filesystem\Factory')->disk('flarum-avatars')->getDriver(); }; $this->app->when('Flarum\Core\Handlers\Commands\UploadAvatarCommandHandler') ->needs('League\Flysystem\FilesystemInterface') - ->give($avatarFilesystem); + ->give($avatarsFilesystem); $this->app->when('Flarum\Core\Handlers\Commands\DeleteAvatarCommandHandler') ->needs('League\Flysystem\FilesystemInterface') - ->give($avatarFilesystem); - - $this->app->bind( - 'Flarum\Core\Repositories\NotificationRepositoryInterface', - 'Flarum\Core\Repositories\EloquentNotificationRepository' - ); + ->give($avatarsFilesystem); } - public function registerGambits() + public function registerDiscussionGambits() { + $this->app->instance('flarum.discussionGambits', [ + 'Flarum\Core\Search\Discussions\Gambits\AuthorGambit', + 'Flarum\Core\Search\Discussions\Gambits\UnreadGambit' + ]); + $this->app->when('Flarum\Core\Search\Discussions\DiscussionSearcher') ->needs('Flarum\Core\Search\GambitManager') - ->give(function () { - $gambits = new GambitManager($this->app); - $gambits->add('Flarum\Core\Search\Discussions\Gambits\AuthorGambit'); - $gambits->add('Flarum\Core\Search\Discussions\Gambits\UnreadGambit'); - $gambits->setFulltextGambit('Flarum\Core\Search\Discussions\Gambits\FulltextGambit'); + ->give(function (Container $app) { + $gambits = new GambitManager($app); - event(new RegisterDiscussionGambits($gambits)); + foreach ($app->make('flarum.discussionGambits') as $gambit) { + $gambits->add($gambit); + } + + $gambits->setFulltextGambit('Flarum\Core\Search\Discussions\Gambits\FulltextGambit'); return $gambits; }); + } + + public function registerUserGambits() + { + $this->app->instance('flarum.userGambits', []); $this->app->when('Flarum\Core\Search\Users\UserSearcher') ->needs('Flarum\Core\Search\GambitManager') - ->give(function () { - $gambits = new GambitManager($this->app); - $gambits->setFulltextGambit('Flarum\Core\Search\Users\Gambits\FulltextGambit'); + ->give(function (Container $app) { + $gambits = new GambitManager($app); - event(new RegisterUserGambits($gambits)); + foreach ($app->make('flarum.userGambits') as $gambit) { + $gambits->add($gambit); + } + + $gambits->setFulltextGambit('Flarum\Core\Search\Users\Gambits\FulltextGambit'); return $gambits; }); } - public function registerPostTypes() + public function addPostTypes() { - Post::addType('Flarum\Core\Models\CommentPost'); - Post::addType('Flarum\Core\Models\DiscussionRenamedPost'); + $this->extend([ + new Extend\PostType('Flarum\Core\Models\CommentPost'), + new Extend\PostType('Flarum\Core\Models\DiscussionRenamedPost') + ]); + } + + public function addEventHandlers() + { + $this->extend([ + new Extend\EventSubscriber('Flarum\Core\Handlers\Events\DiscussionMetadataUpdater'), + new Extend\EventSubscriber('Flarum\Core\Handlers\Events\UserMetadataUpdater'), + new Extend\EventSubscriber('Flarum\Core\Handlers\Events\EmailConfirmationMailer') + ]); + } + + public function bootModels() + { + Model::setValidator($this->app['validator']); CommentPost::setFormatter($this->app['flarum.formatter']); - } - - public function registerEventHandlers($events) - { - $events->subscribe('Flarum\Core\Handlers\Events\DiscussionMetadataUpdater'); - $events->subscribe('Flarum\Core\Handlers\Events\UserMetadataUpdater'); - $events->subscribe('Flarum\Core\Handlers\Events\EmailConfirmationMailer'); - } - - public function setupModels() - { - Model::setForum($this->app['flarum.forum']); - Model::setValidator($this->app['validator']); User::setHasher($this->app['hash']); User::setFormatter($this->app['flarum.formatter']); @@ -179,7 +173,7 @@ class CoreServiceProvider extends ServiceProvider User::registerPreference('indexProfile', 'boolval', true); } - public function registerPermissions() + public function grantPermissions() { Forum::allow('*', function ($forum, $user, $action) { if ($user->hasPermission('forum.'.$action)) { @@ -196,7 +190,7 @@ class CoreServiceProvider extends ServiceProvider // When fetching a discussion's posts: if the user doesn't have permission // to moderate the discussion, then they can't see posts that have been // hidden by someone other than themself. - Discussion::scopeVisiblePosts(function ($query, User $user, Discussion $discussion) { + Discussion::addVisiblePostsScope(function ($query, User $user, Discussion $discussion) { if (! $discussion->can($user, 'editPosts')) { $query->where(function ($query) use ($user) { $query->whereNull('hide_user_id') diff --git a/framework/core/src/Core/Events/RegisterDiscussionGambits.php b/framework/core/src/Core/Events/RegisterDiscussionGambits.php deleted file mode 100644 index 35f885dc8..000000000 --- a/framework/core/src/Core/Events/RegisterDiscussionGambits.php +++ /dev/null @@ -1,13 +0,0 @@ -gambits = $gambits; - } -} diff --git a/framework/core/src/Core/Events/RegisterUserGambits.php b/framework/core/src/Core/Events/RegisterUserGambits.php deleted file mode 100644 index c1e24ce05..000000000 --- a/framework/core/src/Core/Events/RegisterUserGambits.php +++ /dev/null @@ -1,13 +0,0 @@ -gambits = $gambits; - } -} diff --git a/framework/core/src/Core/Formatter/FormatterServiceProvider.php b/framework/core/src/Core/Formatter/FormatterServiceProvider.php new file mode 100644 index 000000000..76b4ab0a6 --- /dev/null +++ b/framework/core/src/Core/Formatter/FormatterServiceProvider.php @@ -0,0 +1,29 @@ +extend([ + new Extend\Formatter('linkify', 'Flarum\Core\Formatter\LinkifyFormatter') + ]); + } + + /** + * Register the service provider. + * + * @return void + */ + public function register() + { + $this->app->singleton('flarum.formatter', 'Flarum\Core\Formatter\FormatterManager'); + } +} diff --git a/framework/core/src/Core/Notifications/NotificationsServiceProvider.php b/framework/core/src/Core/Notifications/NotificationsServiceProvider.php new file mode 100644 index 000000000..6be9c2f65 --- /dev/null +++ b/framework/core/src/Core/Notifications/NotificationsServiceProvider.php @@ -0,0 +1,31 @@ +extend([ + (new Extend\EventSubscriber('Flarum\Core\Handlers\Events\DiscussionRenamedNotifier')), + + (new Extend\NotificationType('Flarum\Core\Notifications\DiscussionRenamedNotification')) + ->subjectSerializer('Flarum\Api\Serializers\DiscussionBasicSerializer') + ->enableByDefault('alert') + ]); + } + + public function register() + { + $this->app->bind( + 'Flarum\Core\Repositories\NotificationRepositoryInterface', + 'Flarum\Core\Repositories\EloquentNotificationRepository' + ); + } +} diff --git a/framework/core/src/Core/Support/MappedMorphTo.php b/framework/core/src/Core/Support/MappedMorphTo.php deleted file mode 100644 index 368592d13..000000000 --- a/framework/core/src/Core/Support/MappedMorphTo.php +++ /dev/null @@ -1,44 +0,0 @@ -map = $map; - - parent::__construct($query, $parent, $foreignKey, $otherKey, $type, $relation); - } - - /** - * Create a new model instance by type. - * - * @param string $type - * @return \Illuminate\Database\Eloquent\Model - */ - public function createModelByType($type) - { - return new $this->map[$type]; - } -} diff --git a/framework/core/src/Core/Support/MappedMorphToTrait.php b/framework/core/src/Core/Support/MappedMorphToTrait.php deleted file mode 100644 index 98fdb98bc..000000000 --- a/framework/core/src/Core/Support/MappedMorphToTrait.php +++ /dev/null @@ -1,49 +0,0 @@ -getMorphs($name, $type, $id); - - // If the type value is null it is probably safe to assume we're eager loading - // the relationship. When that is the case we will pass in a dummy query as - // there are multiple types in the morph and we can't use single queries. - if (is_null($typeValue = $this->$type)) { - return new MappedMorphTo( - $this->newQuery(), - $this, - $id, - null, - $type, - $name, - $classes - ); - } else { - // If we are not eager loading the relationship we will essentially treat this - // as a belongs-to style relationship since morph-to extends that class and - // we will pass in the appropriate values so that it behaves as expected. - $class = $classes[$typeValue]; - $instance = new $class; - - return new MappedMorphTo( - $instance->newQuery(), - $this, - $id, - $instance->getKeyName(), - $type, - $name, - $classes - ); - } - } -} diff --git a/framework/core/src/Extend/ActivityType.php b/framework/core/src/Extend/ActivityType.php index 0de3a0ecc..da52f9fd2 100644 --- a/framework/core/src/Extend/ActivityType.php +++ b/framework/core/src/Extend/ActivityType.php @@ -10,18 +10,27 @@ class ActivityType implements ExtenderInterface protected $serializer; - public function __construct($class, $serializer) + public function __construct($class) { $this->class = $class; + } + + public function subjectSerializer($serializer) + { $this->serializer = $serializer; + + return $this; } public function extend(Container $container) { $class = $this->class; + $type = $class::getType(); - Activity::setSubjectModel($class::getType(), $class::getSubjectModel()); + Activity::setSubjectModel($type, $class::getSubjectModel()); - ActivitySerializer::$subjects[$class::getType()] = $this->serializer; + if ($this->serializer) { + ActivitySerializer::setSubjectSerializer($type, $this->serializer); + } } } diff --git a/framework/core/src/Extend/DiscussionGambit.php b/framework/core/src/Extend/DiscussionGambit.php index b6b983fec..40ee5dbbb 100644 --- a/framework/core/src/Extend/DiscussionGambit.php +++ b/framework/core/src/Extend/DiscussionGambit.php @@ -13,8 +13,6 @@ class DiscussionGambit implements ExtenderInterface public function extend(Container $container) { - $container->make('events')->listen('Flarum\Core\Events\RegisterDiscussionGambits', function ($event) { - $event->gambits->add($this->class); - }); + $container->make('flarum.discussionGambits')[] = $this->class; } } diff --git a/framework/core/src/Extend/NotificationType.php b/framework/core/src/Extend/NotificationType.php index 303b3db4a..4f204cbc6 100644 --- a/framework/core/src/Extend/NotificationType.php +++ b/framework/core/src/Extend/NotificationType.php @@ -13,10 +13,16 @@ class NotificationType implements ExtenderInterface protected $enabled = []; - public function __construct($class, $serializer) + public function __construct($class) { $this->class = $class; + } + + public function subjectSerializer($serializer) + { $this->serializer = $serializer; + + return $this; } public function enableByDefault($method) diff --git a/framework/core/src/Forum/ForumServiceProvider.php b/framework/core/src/Forum/ForumServiceProvider.php index 7b809c077..e61d63eb4 100644 --- a/framework/core/src/Forum/ForumServiceProvider.php +++ b/framework/core/src/Forum/ForumServiceProvider.php @@ -20,6 +20,8 @@ class ForumServiceProvider extends ServiceProvider return new UrlGenerator($this->app->make('flarum.forum.routes')); } ); + + $this->app->register('Flarum\Locale\LocaleServiceProvider'); } /** diff --git a/framework/core/src/Locale/LocaleServiceProvider.php b/framework/core/src/Locale/LocaleServiceProvider.php new file mode 100644 index 000000000..4f0b5801d --- /dev/null +++ b/framework/core/src/Locale/LocaleServiceProvider.php @@ -0,0 +1,34 @@ +setupLocale('en'); + } + + public function setupLocale($locale) + { + $dir = __DIR__.'/../../locale/'.$locale; + + $this->extend( + (new Extend\Locale($locale)) + ->translations($dir.'/translations.yml') + ->config($dir.'/config.php') + ->js($dir.'/config.js') + ); + } + + public function register() + { + $this->app->singleton('flarum.localeManager', 'Flarum\Locale\LocaleManager'); + } +}